一、栈
使用栈这种数据结构作为辅助空间最典型的情况就是当前元素需要与前面的元素做比较 或者在树、图中化递归为非递归
20. Valid Parentheses
Given a string containing just the characters '('
, ')'
, '{'
, '}'
, '['
and ']'
, determine if the input string is valid.
An input string is valid if:
- Open brackets must be closed by the same type of brackets.
- 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](https://i-blog.csdnimg.cn/blog_migrate/d12faba5ad1b3bc665e4e15b307496c5.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