Using Stack - How to Succeed in Algorithms


Using Stack - How to Succeed in Algorithms

How to Succeed in Algorithms Interview Series


Applications of Stack

  • parentheses
  • calculator: +-*/
  • priority

Implementation Detail of Using Stack

  • Use ArrayDeque or LinkedList
    • we can push/pop at both ends
  • what to store in stack, its meaning
  • when to pop out

Examples of Using Stack

Stack + Greedy

  • 运用Stack加贪心法的题目有很多,这类问题的做法是遍历输入数组,当前元素与栈顶元素比较,如果当前元素更优则pop栈顶元素,直到栈顶元素更优为止,而后插入当前元素。
  • LeetCode 316 - Remove Duplicate Letters
public String removeDuplicateLetters(String sr) {

    int[] res = new int[26]; //will contain number of occurences of character (i+'a')
    boolean[] visited = new boolean[26]; //will contain if character (i+'a') is present in current result Stack
    char[] ch = sr.toCharArray();
    for(char c: ch){  //count number of occurences of character
        res[c-'a']++;
    }
    Stack<Character> st = new Stack<>(); // answer stack
    int index;
    for(char s:ch){
        index= s-'a';
        res[index]--;   //decrement number of characters remaining in the string to be analysed
        if(visited[index]) //if character is already present in stack, dont bother
            continue;
        //if current character is smaller than last character in stack which occurs later in the string again
        //it can be removed and  added later e.g stack = bc remaining string abc then a can pop b and then c
        while(!st.isEmpty() && s<st.peek() && res[st.peek()-'a']!=0){
            visited[st.pop()-'a']=false;
        }
        st.push(s); //add current character and mark it as visited
        visited[index]=true;
    }

    StringBuilder sb = new StringBuilder();
    //pop character from stack and build answer string from back
    while(!st.isEmpty()){
        sb.insert(0,st.pop());
    }
    return sb.toString();
}
  • LeetCode 654 - Maximum Binary Tree
    • decreasing stack
    • create the TreeNode while access the data, push them into monotone stack, connect TreeNodes when push or pop
    public TreeNode constructMaximumBinaryTree(int[] nums) {
      Deque<TreeNode> stack = new LinkedList<>();
      for(int i = 0; i < nums.length; i++) {
          TreeNode curr = new TreeNode(nums[i]);
          while(!stack.isEmpty() && stack.peek().val < nums[i]) {
              curr.left = stack.pop();
          }
          if(!stack.isEmpty()) {
              stack.peek().right = curr;
          }
          stack.push(curr);
      }    
      return stack.isEmpty() ? null : stack.removeLast();
    }

Examples

public void reverseStack(Stack<Integer> stack){
 if(stack.isEmpty())
  return ;
 int val= stack.pop();
 reverseStack(stack);
 pushToBottom(stack,val);
 return ;
}
private void pushToBottom(Stack<Integer> stack,int item){
 if(stack.isEmpty()){
  stack.push(item);
  return ;
 }
 int val= stack.pop();
 pushToBottom(stack,item);
 stack.push(val);
}
  • LeetCode 889 - Construct Binary Tree from Preorder and Postorder Traversal
    public TreeNode constructFromPrePost(int[] pre, int[] post) {
      Deque<TreeNode> s = new ArrayDeque<>();
      s.offer(new TreeNode(pre[0]));
      for (int i = 1, j = 0; i < pre.length; ++i) {
          TreeNode node = new TreeNode(pre[i]);
          while (s.getLast().val == post[j]) {
              s.pollLast(); j++;
          }
          if (s.getLast().left == null) s.getLast().left = node;
          else s.getLast().right = node;
          s.offer(node);
      }
      return s.getFirst();
    }
  • LeetCode 255 - Verify Preorder Sequence in Binary Search Tree
    public boolean verifyPreorder(int[] preorder) {
      Stack<Integer> stk = new Stack<Integer>();
      int min = Integer.MIN_VALUE;
      for(int num : preorder){
          if(num < min) return false;
          while(!stk.isEmpty() && num > stk.peek()){
              min = stk.pop();
          }
          stk.push(num);
      }
      return true;
    }
    public boolean IsValidPostOrderBst(int[] nums)
    {
      int i = nums.length;
      int max = Integer.MAX_VALUE;
      for (int j = nums.length - 1; j >= 0; j--)
      {
          if (nums[j] > max) return false;
          while (i <= nums.length - 1 && nums[j] > nums[i])
              max = nums[i++];
          nums[--i] = nums[j];
      }
      return true;
    }
  • LeetCode 341 - Flatten Nested List Iterator
    public class NestedIterator implements Iterator<Integer> {
      Stack<Iterator<NestedInteger>> stack;
      Integer nextInteger;
      public NestedIterator(List<NestedInteger> nestedList) {
          stack = new Stack<Iterator<NestedInteger>>();
          stack.push(nestedList.iterator());
          nextInteger = null;
      }
      public Integer next() {
          Integer next = null;
          if(hasNext()) {
              next = nextInteger;
              nextInteger=null;
          }
          return next;
      }
      public boolean hasNext() {
          if(nextInteger==null) {
              while(!stack.isEmpty()) {
              Iterator<NestedInteger> cIterator = stack.peek();
              if(cIterator.hasNext()) {
                  NestedInteger c = cIterator.next();
                  if(c.isInteger()) {
                      nextInteger = c.getInteger();
                      return true;
                  } else {
                      stack.push(c.getList().iterator());
                  }
              }
              else stack.pop();
          }
            return false;
          } else return true;
      }   
    }
  • HARD LeetCode 394 - Decode String
    public String decodeString(String s) {
      String res = "";
      Stack<Integer> countStack = new Stack<>();
      Stack<String> resStack = new Stack<>();
      int idx = 0;
      while (idx < s.length()) {
          if (Character.isDigit(s.charAt(idx))) {
              int count = 0;
              while (Character.isDigit(s.charAt(idx))) {
                  count = 10 * count + (s.charAt(idx) - '0');
                  idx++;
              }
              countStack.push(count);
          }
          else if (s.charAt(idx) == '[') {
              resStack.push(res);
              res = "";
              idx++;
          }
          else if (s.charAt(idx) == ']') {
              StringBuilder temp = new StringBuilder (resStack.pop());
              int repeatTimes = countStack.pop();
              for (int i = 0; i < repeatTimes; i++) {
                  temp.append(res);
              }
              res = temp.toString();
              idx++;
          }
          else {
              res += s.charAt(idx++);
          }
      }
      return res;
    }
  • LeetCode 653 - Two Sum IV - Input is a BST
    • two stacks, two pointers + iterators
    public boolean findTarget(TreeNode root, int k) {
      Stack<TreeNode> stackL = new Stack<TreeNode>();  // iterator 1 that gets next smallest value
      Stack<TreeNode> stackR = new Stack<TreeNode>();  // iterator 2 that gets next largest value
      for(TreeNode cur = root; cur != null; cur = cur.left)  
          stackL.push(cur);
      for(TreeNode cur = root; cur != null; cur = cur.right)  
          stackR.push(cur);
      while(stackL.size() != 0 && stackR.size() != 0 && stackL.peek() != stackR.peek()){
          int tmpSum = stackL.peek().val + stackR.peek().val;
          if(tmpSum == k)  return true;
          else if(tmpSum < k)
              for(TreeNode cur = stackL.pop().right; cur != null; cur = cur.left)
                  stackL.push(cur);
          else
              for(TreeNode cur = stackR.pop().left; cur != null; cur = cur.right)
                  stackR.push(cur);
      }
      return false;
    }
  • LeetCode 103 - Binary Tree Zigzag Level Order Traversal
    • Queue + Dequeue
    • dfs for fun: travel(TreeNode curr, List<List> sol, int level)
    • print directly: using 2 stacks
      • or use 2 Dequeue
      void printSpiral(Node node)
      {
      if (node == null)
          return; // NULL check
      // Create two stacks to store alternate levels
      // For levels to be printed from right to left
      Stack<Node> s1 = new Stack<Node>();  
      // For levels to be printed from left to right
      Stack<Node> s2 = new Stack<Node>();  
      // Push first level to first stack 's1'
      s1.push(node);
      // Keep printing while any of the stacks has some nodes
      while (!s1.empty() || !s2.empty()) {
          // Print nodes of current level from s1 and push nodes of
          // next level to s2
          while (!s1.empty()) {
              Node temp = s1.peek();
              s1.pop();
              System.out.print(temp.data + " ");
              // Note that is right is pushed before left
              if (temp.right != null)
                  s2.push(temp.right);
              if (temp.left != null)
                  s2.push(temp.left);
          }
          // Print nodes of current level from s2 and push nodes of
          // next level to s1
          while (!s2.empty()) {
              Node temp = s2.peek();
              s2.pop();
              System.out.print(temp.data + " ");
              // Note that is left is pushed before right
              if (temp.left != null)
                  s1.push(temp.left);
              if (temp.right != null)
                  s1.push(temp.right);
          }
      }
      }
  • LeetCode 430 - Flatten a multilevel linked list
    public Node flatten(Node h) {
      if (h == null) return h;
      Stack<Node> st = new Stack<>();
      Node prev = null;
      st.push(h);
      while (!st.isEmpty()){
          Node cur = st.pop();
          if (prev != null) {
              prev.next = cur;
              cur.prev = prev;
              prev.child = null;
          }
          if (cur.next != null) st.push(cur.next);
          if (cur.child != null) st.push(cur.child);
          prev = cur;
      }    
      return h;
    }

Simple Examples of Using Stack

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)