棧與隊列相關算法總結

一、棧

    使用棧這種數據結構作爲輔助空間最典型的情況就是當前元素需要與前面的元素做比較  或者在樹、圖中化遞歸爲非遞歸

20. Valid Parentheses

Given a string containing just the characters '('')''{''}''[' and ']', determine if the input string is valid.

An input string is valid if:

  1. Open brackets must be closed by the same type of brackets.
  2. Open brackets must be closed in the correct order

代碼如下:

class Solution {
    public boolean isValid(String s) {
	Stack<Character> stack = new Stack<Character>();
	for(char c : s.toCharArray()){
        if(c == '('){
            stack.push(')');
        }else if(c == '['){
            stack.push(']');
        }else if(c== '{'){
            stack.push('}');
        }else{
        if(stack.isEmpty() || stack.pop() != c){
            return false;
        }
        }
    }
            return stack.isEmpty();
  }
}

 

150. Evaluate Reverse Polish Notation

Evaluate the value of an arithmetic expression in Reverse Polish Notation.

Valid operators are +-*/. Each operand may be an integer or another expression.

Example 2:

Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6

Example 3:

Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
Output: 22
Explanation: 
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

代碼如下:

public class Solution {
    public int evalRPN(String[] tokens) {
        int a,b;
		Stack<Integer> S = new Stack<Integer>();
		for (String s : tokens) {
			if(s.equals("+")) {
				S.add(S.pop()+S.pop());
			}
			else if(s.equals("/")) {
				b = S.pop();
				a = S.pop();
				S.add(a / b);
			}
			else if(s.equals("*")) {
				S.add(S.pop() * S.pop());
			}
			else if(s.equals("-")) {
				b = S.pop();
				a = S.pop();
				S.add(a - b);
			}
			else {
				S.add(Integer.parseInt(s));
			}
		}	
		return S.pop();
	}
}

 

二叉樹前序遍歷:

144. Binary Tree Preorder Traversal

//遞歸
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
		List<Integer> pre = new LinkedList<Integer>();
		if(root==null) return pre;
		pre.add(root.val);
		pre.addAll(preorderTraversal(root.left));
		pre.addAll(preorderTraversal(root.right));
		return pre;
	}
}

//非遞歸 使用Stack輔助
public class Solution {
   public List<Integer> preorderIt(TreeNode root) {
		List<Integer> pre = new LinkedList<Integer>();
		if(root==null) return pre;
		Stack<TreeNode> tovisit = new Stack<TreeNode>();
		tovisit.push(root);
		while(!tovisit.isEmpty()) {
			TreeNode visiting = tovisit.pop();
			pre.add(visiting.val);
			if(visiting.right!=null) tovisit.push(visiting.right);
			if(visiting.left!=null) tovisit.push(visiting.left);
		}
		return pre;
	}
}

//可以在查一下一種線索樹方法遍歷,空間複雜度爲O(1)

 

二叉樹中序遍歷:

144. Binary Tree Preorder Traversal

//遞歸

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
                List<Integer> pre = new LinkedList<Integer>();
		if(root==null) return pre;
	        pre.addAll(inorderTraversal(root.left));
                pre.add(root.val);
		pre.addAll(inorderTraversal(root.right));
		return pre;
   }
}


//非遞歸
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> list = new ArrayList<Integer>();

    Stack<TreeNode> stack = new Stack<TreeNode>();
    TreeNode cur = root;

    while(cur!=null || !stack.empty()){
        while(cur!=null){
            stack.add(cur);
            cur = cur.left;
        }
        cur = stack.pop();
        list.add(cur.val);
        cur = cur.right;
    }

    return list;
}
}

 

二叉樹後續遍歷:

145. Binary Tree Postorder Traversal

//就是前序遍歷 只不過每次都是增加到list的頭部 前序遍歷增加到尾部
class Solution {
   public List<Integer> postorderTraversal(TreeNode root) {
	  LinkedList<Integer> ans = new LinkedList<>();
	  Stack<TreeNode> stack = new Stack<>();
	  if (root == null) return ans;
	
	  stack.push(root);
	  while (!stack.isEmpty()) {
		  TreeNode cur = stack.pop();
		  ans.addFirst(cur.val);
		  if (cur.left != null) {
		  	stack.push(cur.left);
	  	  }
		  if (cur.right != null) {
			stack.push(cur.right);
		 } 
 	  }
	return ans;
    }
}

 

 

二、隊列

廣度優先遍歷BFS:

102. Binary Tree Level Order Traversal

代碼如下:

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> wrapList =  new  ArrayList<List<Integer>>();
        Queue<TreeNode> qu = new LinkedList<TreeNode>();
         if(root == null) return wrapList;
        qu.offer(root);
        while(!qu.isEmpty()){
            int size = qu.size();
            List<Integer> list = new  ArrayList<Integer>();
            for(int i=0; i<size; i++){
                TreeNode node = qu.poll();
                list.add(node.val);
                if(node.left!=null){
                   qu.offer(node.left); 
                }
                if(node.right!=null){
                    qu.offer(node.right);
                }
                
            }
            wrapList.add(list); 
        }
      return wrapList;      
    }
}

 

 

107. Binary Tree Level Order Traversal II

Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root).返回是一個從低至上的list

代碼如下:

//BFS
//因爲定義了一個level,所以可以按遞歸的方法來隨便訪問左右子樹,因爲有level每次都可以獲取到相應的ArrayList
public class Solution {
        public List<List<Integer>> levelOrderBottom(TreeNode root) {
            List<List<Integer>> wrapList = new LinkedList<List<Integer>>();
            levelMaker(wrapList, root, 0);
            return wrapList;
        }
        
        public void levelMaker(List<List<Integer>> list, TreeNode root, int level) {
            if(root == null) return;
            if(level >= list.size()) {
                list.add(0, new LinkedList<Integer>());
            }
            levelMaker(list, root.left, level+1);
            levelMaker(list, root.right, level+1);
            list.get(list.size()-level-1).add(root.val);
        
    }
}


//DFS


public class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        List<List<Integer>> wrapList = new LinkedList<List<Integer>>();
        
        if(root == null) return wrapList;
        
        queue.offer(root);
        while(!queue.isEmpty()){
            int levelNum = queue.size();
            List<Integer> subList = new LinkedList<Integer>();
            for(int i=0; i<levelNum; i++) {
                if(queue.peek().left != null) queue.offer(queue.peek().left);
                if(queue.peek().right != null) queue.offer(queue.peek().right);
                subList.add(queue.poll().val);
            }
            wrapList.add(0, subList);
        }
        return wrapList;
    }
}

 

103. Binary Tree Zigzag Level Order Traversal

Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).

//跟上面107用bfs解決思想一幕一樣  因爲定義了一個level,每次都可以獲取到相應的ArrayList
//所以只要按左右 右左子樹順序隨便隨便遞歸訪問
public class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) 
    {
        List<List<Integer>> sol = new ArrayList<>();
        travel(root, sol, 0);
        return sol;
    }
    
    private void travel(TreeNode curr, List<List<Integer>> sol, int level)
    {
        if(curr == null) return;
        
        if(sol.size() <= level)
        {
            List<Integer> newLevel = new LinkedList<>();
            sol.add(newLevel);
        }
        
        List<Integer> collection  = sol.get(level);
        if(level % 2 == 0) collection.add(curr.val);
        else collection.add(0, curr.val);
        
        travel(curr.left, sol, level + 1);
        travel(curr.right, sol, level + 1);
    }
}

 

199. Binary Tree Right Side View

Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.

public class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        rightView(root, result, 0);
        return result;
    }
    
    public void rightView(TreeNode curr, List<Integer> result, int currDepth){
        if(curr == null){
            return;
        }
        if(currDepth == result.size()){
            result.add(curr.val);
        }
        
//爲什麼可以用這種方法是由於if(currDepth == result.size())這個判斷會保持只add最右側節點,因爲到左子樹的時候currDepth != result.size()就不會添加了

        rightView(curr.right, result, currDepth + 1);
        rightView(curr.left, result, currDepth + 1);//加上這行代碼是爲了防止右子樹爲空,會看到 
         左子樹的數據,這種特殊情況
        
    }
}
uploading.4e448015.gif正在上傳…重新上傳取消

 

279. Perfect Squares(無權圖的最短路徑bfs)

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.

Input: n = 12
Output: 3 
Explanation: 12 = 4 + 4 + 4.

代碼如下:(無權圖的最短路徑問題,然後求最小路徑問題,最後用bfs求最小路徑)

//圖的bfs
class Solution {
  public int numSquares(int n) {
    Queue<Integer> q = new LinkedList<>();
    Set<Integer> visited = new HashSet<>();
    q.offer(0);
    visited.add(0);
    int depth = 0;
    while(!q.isEmpty()) {
        int size = q.size();
        depth++;
        while(size-- > 0) {
            int u = q.poll();
            for(int i = 1; i*i <= n; i++) {
                int v = u+i*i;
                if(v == n) {
                    return depth;
                }
                if(v > n) {
                    break;
                }
                if(!visited.contains(v)) {
                    q.offer(v);
                    visited.add(v);
                }
            }
        }
    }
    return depth;
  }
}



//dp實現


public int numSquares(int n) {

    // Algorithm: starting from k=sqrt(n), then k decreasing 1 at time, choose the minimum one
    // using dp[n] to mem the ones already calculated
    int[] dp = new int[n+1];
    return find(n, dp);
}

int find(int n, int[]dp) {
    int m = Integer.MAX_VALUE;
    
    if(dp[n]!=0) {
        return dp[n];
    }
    
    if(n<4) {
        return n;
    }
    
    int k=(int)Math.sqrt(n);        
    for(int j=k; j>0; j--) {
        m = Math.min(m, 1+find(n-j*j, dp));           
    }
    
    dp[n] = m;
    return m;
}

 

 

三、優先隊列(底層用堆實現的)

詳見我的另一個博客:https://www.cnblogs.com/yangcao/p/11651047.html

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章