题目链接
题目描述
给定一个整数数组 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
解题思路
这道题的难点在于分析碰撞的场景,需要明确什么时候可以直接入栈,什么时候需要判断
直接入栈无需判断(不会发生碰撞)的情况:
1、栈为空
2、栈顶元素为负(此时当前元素为负则一起向左,为正则分向两边)
3、当前元素为正(栈顶为正则一起向右,栈顶为负则分向两边)
会发生碰撞的情况:
1、abs(栈顶元素)大于abs(当前元素),当前元素被摧毁
2、abs(栈顶元素)等于abs(当前元素),栈顶弹出和当前元素抵消
3、abs(栈顶元素)小于abs(当前元素),栈顶弹出,当前元素继续比较新的栈
最终返回栈
代码
Python
class Solution:
def asteroidCollision(self, asteroids: list[int]) -> list[int]:
stack, i = [], 0
while i < len(asteroids):
if not stack or stack[-1] < 0 or asteroids[i] > 0:
stack.append(asteroids[i])
elif stack[-1] <= -asteroids[i]:
if stack.pop() < -asteroids[i]:
continue
i += 1
return stack
Go
type stack []int
func (s *stack) push(a int) {
*s = append(*s, a)
}
func (s *stack) pop() int {
a := *s
if len(a) == 0 {
return 0
}
ans := a[len(a)-1]
*s = a[:len(a)-1]
return ans
}
func asteroidCollision(asteroids []int) []int {
var s stack
for i := 0; i < len(asteroids); {
if len(s) == 0 || s[len(s)-1] < 0 || asteroids[i] > 0 {
s.push(asteroids[i])
} else {
if s[len(s)-1] <= -asteroids[i] {
if s.pop() < -asteroids[i] {
continue
}
}
}
i++
}
return s
}