题目链接及描述
. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/asteroid-collision/description/?envType=study-plan-v2&envId=leetcode-75
题目分析
单调栈题目,根据题目描述,当两个行星运动方向不同可能发生碰撞,为什么说是可能发生碰撞,这里是自己踩的一个小坑。
两颗行星运动方向不同也就是 num1 * num2 < 0,此时这两颗行星一定会发生碰撞吗?当然不是,只有左边的行星向右运动,并且右边的行星向左运动此时才会发生碰撞,对应为【+ -】;与之相对的一种状态【- +】此时最左边的行星向左边运动,最右边的行星向右边运动,此时并不会发生碰撞。自己第一次编写代码就将循环条件设置为了 num1 * num2 < 0,实则不然,正确的循环条件应该为num1 > 0 && num2 < 0。
本题正确解乏,借助栈的思想,栈中存放的都是碰撞结束后存留的行星,每当遍历到一个新的行星,将其与栈中最右侧的行星进行比较,如果满足碰撞条件:栈不为空 && num1 > 0 && num2 < 0,此时将栈中最右侧元素与遍历新元素进行比较进行留存。
这里需要注意的是使用留存的新元素继续与栈顶的元素进行比较,看是否满足碰撞条件,满足碰撞条件继续进行元素留存以及循环比较。直至不满足碰撞条件随后退出循环,将留存后的元素加入到栈顶。
需要注意对碰撞抵消这种情况的处理。【10, -10】碰撞后两个行星全部消失。
代码编写
class Solution {
public int[] asteroidCollision(int[] asteroids) {
Deque<Integer> dq = new ArrayDeque<>();
for(int asteroid : asteroids){
// 只有最新的小行星向左运动,并且未碰撞的最右侧的小行星向右运动才会碰撞
while(!dq.isEmpty() && asteroid < 0 && dq.peekLast() > 0){
int top = dq.pollLast();
if(Math.abs(top) > Math.abs(asteroid)){
asteroid = top;
}else if(Math.abs(top) == Math.abs(asteroid)){
asteroid = 0;
}
}
if(asteroid != 0){
dq.addLast(asteroid);
}
}
int[] ans = new int[dq.size()];
int idx = 0;
for(int num : dq){
ans[idx++] = num;
}
return ans;
}
}