题目
给定一个整数数组 asteroids,表示在同一行的小行星。数组中小行星的索引表示它们在空间中的相对位置。
对于数组中的每一个元素,其绝对值表示小行星的大小,正负表示小行星的移动方向(正表示向右移动,负表示向左移动)。每一颗小行星以相同的速度移动。
找出碰撞后剩下的所有小行星。碰撞规则:两个小行星相互碰撞,较小的小行星会爆炸。如果两颗小行星大小相同,则两颗小行星都会爆炸。两颗移动方向相同的小行星,永远不会发生碰撞。
一、代码实现
func asteroidCollision(asteroids []int) []int {
stack := make([]int, 0)
for _, aster := range asteroids {
alive := true // 标记当前小行星是否存活
// 当栈顶行星向右,当前行星向左时触发碰撞检测
for alive && len(stack) > 0 && aster < 0 && stack[len(stack)-1] > 0 {
top := stack[len(stack)-1]
if top > -aster { // 栈顶行星更大
alive = false
} else if top == -aster { // 同归于尽
stack = stack[:len(stack)-1]
alive = false
} else { // 当前行星更大,栈顶爆炸
stack = stack[:len(stack)-1]
}
}
if alive {
stack = append(stack, aster)
}
}
return stack
}
二、算法分析
1. 核心思路
- 栈结构特性:利用后进先出(LIFO)特性模拟碰撞顺序
- 碰撞检测优化:仅在右向行星(正数)遇到左向行星(负数)时触发计算
2. 关键步骤
- 栈初始化:创建空栈存储存活行星
- 碰撞处理循环:
- 当栈顶行星向右且当前行星向左时进入碰撞判断
- 比较大小决定爆炸情况(三种分支)
- 存活判断:未爆炸的行星入栈
3. 复杂度
指标 | 值 | 说明 |
---|---|---|
时间复杂度 | O(n) | 每个元素最多入栈、出栈各一次 |
空间复杂度 | O(n) | 栈存储最坏情况保存全部元素 |
三、图解示例
四、边界条件与扩展
1. 特殊场景验证
- 全右向行星:
[1,5,3]
→ 直接返回原数组 - 连续爆炸:
[10,2,-15]
→[-15]
(2和10先后爆炸) - 边缘爆炸:
[1,1,-1,-1]
→[]
(两对行星同归于尽)
2. 多语言实现
# Python实现(列表模拟栈)
def asteroidCollision(asteroids):
stack = []
for aster in asteroids:
while stack and aster < 0 and stack[-1] > 0:
if stack[-1] < -aster:
stack.pop()
elif stack[-1] == -aster:
stack.pop()
break
else:
break
else:
stack.append(aster)
return stack
// Java实现(双端队列优化)
public int[] asteroidCollision(int[] asteroids) {
Deque<Integer> stack = new ArrayDeque<>();
for (int aster : asteroids) {
boolean alive = true;
while (!stack.isEmpty() && aster < 0 && stack.peekLast() > 0) {
if (stack.peekLast() < -aster) {
stack.pollLast();
} else if (stack.peekLast() == -aster) {
stack.pollLast();
alive = false;
break;
} else {
alive = false;
break;
}
}
if (alive) stack.addLast(aster);
}
return stack.stream().mapToInt(i->i).toArray();
}
3. 算法对比
方法 | 时间复杂度 | 空间复杂度 | 优势 |
---|---|---|---|
栈模拟法 | O(n) | O(n) | 最优时间复杂度 |
暴力枚举法 | O(n²) | O(1) | 仅适用于教学演示 |
递归回溯法 | O(2^n) | O(n) | 理论价值大于实用价值 |
五、总结与扩展
1. 核心创新点
- 动态碰撞检测:通过栈的实时更新实现高效碰撞模拟
- 条件分支优化:仅处理右→左碰撞场景,降低计算复杂度
2. 数学本质
设总行星数n,碰撞次数k,则时间复杂度严格满足O(n+k),因k<n,最终复杂度为O(n)
3. 扩展应用
- 括号匹配:处理嵌套结构时类似的栈操作逻辑
- 交通流模拟:车辆变道冲突检测的离散事件模型
- 游戏物理引擎:粒子碰撞检测的简化实现方案
- 内存管理:类似malloc内存块的合并与分割操作