Stack解题套路

java中使用Stack类: (判断空: stack.empty() 跟 queue.isEmpty()不一样,要注意)

Stack<T> stack = new Stack<>();
stack.push(x);
while (!stack.empty()) {
    T cur = stack.pop();
    T next = stack.peek();
}

更好的是使用Deque接口(接口更一致,isEmpty(), 然后效率比Stack和LinkedList都要高):

Deque<T> stack = new ArrayDeque<>();
stack.push(X); 
stack.peek(); 
stack.isEmpty();  
stack.pop();

对比Queue的接口:

Qeueu<T> que = new LinkedList<>();
while (!que.isEmpty()) {
	int size = que.size();
	for(int i = 0; i < size; i++) {
		T cur = que.poll();
		que.offer(next);	
	}
}

定义Stack的含义:

  • arr[i]左边所有比arr[i] 大的数(那么stack中保存的数据是单调的,从栈底到顶是)
  • 递归之前的函数状态(Call Stack)

题目

739. 每日温度 - 力扣(LeetCode)

how many number of days you have to wait after the ith day to get a warmer temperature?

  • 方法1: 从左到右遍历: 等到warmer temp时,更新前面低温的天,需要等待的天数 => stack中保存的是比当前温度高的天(温度低的天弹出,更新答案) [底->顶: 递减的]
  • 方法2: 从右到左遍历: 已知右边的温度,更新当前天的信息,栈顶保存的是比当前天温度高的(比当前温度低的弹出),更新当前答案 [底->顶: 递减的]
  • 这两种方法对应两种使用stack的思路,方法1是利用当前值更新栈中的部分元素的答案,方法2是利用栈中的信息更新当前值的答案。

方法1:

  public int[] dailyTemperatures(int[] temp) {
    // 思路:使用stack保存从左到右处理过程中比当前arr[i]高的温度(比当前arr[i]低的温度,弹出进行更新处理)
    int n = temp.length;
    int[] ans = new int[n];
    Stack<Integer> stack = new Stack<>();
    for(int i = 0; i < n; i++) {
        while (!stack.empty() && temp[i] > temp[stack.peek()]) {
            int idx = stack.pop();
            ans[idx] = i - idx;
        }
        stack.push(i);
    }
    // while (!stack.empty()) {
    //     int idx = stack.pop();
    //     ans[idx] = 0; // ans intialized with 0, so skip to process
    // }
    return ans;
}

方法2:

 public int[] dailyTemperatures(int[] temp) {
    // 思路:使用stack保存从右到左处理过程中比当前arr[i]高的温度(比当前arr[i]低的温度,弹出),更新当前的答案
    int n = temp.length;
    int[] ans = new int[n];
    Stack<Integer> stack = new Stack<>();
    for(int i = n - 1; i >= 0; i--) {
        while (!stack.empty() && temp[i] >= temp[stack.peek()]) {
            stack.pop();
        }
        if (stack.empty()) {
            ans[i] = 0;
        } else {
            ans[i] = stack.peek() - i;
        }
        stack.push(i);
    }
    return ans;
}

735. 行星碰撞 - 力扣(LeetCode)

stack保存的是从左到右,目前还存活的小行星。每当碰到一个往左移动的行星,才需要考虑是否有碰撞,从而更新stack。

public int[] asteroidCollision(int[] asteroids) {
    int n = asteroids.length;
    Stack<Integer> stack = new Stack<>();
    for(int i = 0; i < n; i++) {
        if (asteroids[i] < 0) {
            // stack loses
            while (!stack.empty() && stack.peek() > 0 && stack.peek() < -asteroids[i]) {
                stack.pop();
            }
            // both loses
            if (!stack.empty() && stack.peek() > 0 && stack.peek() == -asteroids[i]) {
                stack.pop();
            } else if (stack.empty() || stack.peek() <= 0) {
               stack.push(asteroids[i]);
            } // otherwise stack wins
        } else {
            stack.push(asteroids[i]);
        }
    }
    int[] ans = new int[stack.size()];
    for(int i = ans.length - 1; i >= 0; i--) {
        ans[i] = stack.pop();
    }
    return ans;
}
posted @ 2023-05-21 10:07  编程爱好者-java  阅读(21)  评论(0编辑  收藏  举报