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;
}