思路
栈,最小栈,单调栈
例题
735. 行星碰撞
给定一个整数数组 asteroids,表示在同一行的行星。
对于数组中的每一个元素,其绝对值表示行星的大小,正负表示行星的移动方向(正表示向右移动,负表示向左移动)。每一颗行星以相同的速度移动。
找出碰撞后剩下的所有行星。碰撞规则:两个行星相互碰撞,较小的行星会爆炸。如果两颗行星大小相同,则两颗行星都会爆炸。两颗移动方向相同的行星,永远不会发生碰撞。
示例 1:
输入:asteroids = [5,10,-5]
输出:[5,10]
解释:10 和 -5 碰撞后只剩下 10 。 5 和 10 永远不会发生碰撞。
示例 2:
输入:asteroids = [8,-8]
输出:[]
解释:8 和 -8 碰撞后,两者都发生爆炸。
示例 3:
输入:asteroids = [10,2,-5]
输出:[10]
解释:2 和 -5 发生碰撞后剩下 -5 。10 和 -5 发生碰撞后剩下 10 。
示例 4:
输入:asteroids = [-2,-1,1,2]
输出:[-2,-1,1,2]
解释:-2 和 -1 向左移动,而 1 和 2 向右移动。 由于移动方向相同的行星不会发生碰撞,所以最终没有行星发生碰撞。
提示:
2 <= asteroids.length <= 104
-1000 <= asteroids[i] <= 1000
asteroids[i] != 0
解题思路
思路一
本题可使用栈这个数据结构进行辅助判断。将数组中的行星元素依次放入栈中,每次压入栈的时候,与栈顶元素进行进行判断,是否能碰撞消除。最终栈中留下来的元素就是碰撞后剩下的行星。
- 思路
- 边界
- 细节
- 优化
- 代码实现
public int[] asteroidCollision(int[] asteroids) {
if (asteroids == null || asteroids.length == 0) {
return new int[] {};
}
LinkedList<Integer> stack = new LinkedList<>();
for (int i = 0; i < asteroids.length; i++) {
boolean flag = true;
while (!stack.isEmpty() && stack.peek() > 0 && asteroids[i] < 0) {
if (Math.abs(asteroids[i]) > stack.peek()) {
stack.pop();
} else if (Math.abs(asteroids[i]) == stack.peek()) {
stack.pop();
flag = false;
break;
} else {
flag = false;
break;
}
}
if (flag) {
stack.push(asteroids[i]);
}
}
int[] result = new int[stack.size()];
for (int i = 0; i < result.length; i++) {
result[i] = stack.removeLast();
}
return result;
}
最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
思路一
使用一个辅助栈,从上到下保存栈的最小值。
细节
辅助栈的入栈判断条件是细节,注意是等号,而且如果辅助栈为空的时候,也是可以入栈的
代码
public class LeetCode155 {
Deque<Integer> stack1 = new ArrayDeque<>();
Deque<Integer> stack2 = new ArrayDeque<>();
public LeetCode155() {
stack1 = new ArrayDeque<>();
stack2 = new ArrayDeque<>();
}
public void push(int val) {
stack1.push(val);
if (stack2.isEmpty() || stack2.peek() >= val) { // 判断条件是细节,注意是等号,而且如果辅助栈为空的时候,也是可以入栈的
stack2.push(val);
}
}
public void pop() {
if (!stack1.isEmpty()) {
int pop = stack1.pop();
if (!stack2.isEmpty() && stack2.peek() == pop) {
stack2.pop();
}
}
}
public int top() {
if (!stack1.isEmpty()) {
return stack1.peek();
}
throw new RuntimeException("栈中元素为空,此操作非法");
}
public int getMin() {
return stack2.peek();
}
}
思路二
不适用辅助栈。
将前一个最小值保存起来,保存到栈中。
代码
class MinStack {
Deque<Integer> stack1;
int min;
public MinStack() {
stack1 = new ArrayDeque<>();
min = Integer.MAX_VALUE;
}
public void push(int val) {
if (val <= min) {
int preMin = min;
stack1.push(preMin);// 保存之前的min值
min = val;
}
stack1.push(val);
}
public void pop() {
if (!stack1.isEmpty()) {
int pop = stack1.pop();
if (pop == min) {
int preMin = stack1.pop();// 弹出前一个最小值
min = preMin;
}
}
}
public int top() {
if (!stack1.isEmpty()) {
return stack1.peek();
}
throw new RuntimeException("stack is empty");
}
public int getMin() {
return min;
}
}
思路三
用数组实现栈