LC 735. 行星碰撞

题目描述

这是 LeetCode 上的 735. 行星碰撞 ,难度为 中等

给定一个整数数组 asteroids,表示在同一行的行星。

对于数组中的每一个元素,其绝对值表示行星的大小,正负表示行星的移动方向(正表示向右移动,负表示向左移动)。

每一颗行星以相同的速度移动,找出碰撞后剩下的所有行星。

碰撞规则:

  1. 两个行星相互碰撞,较小的行星会爆炸。
  2. 如果两颗行星大小相同,则两颗行星都会爆炸。
  3. 两颗移动方向相同的行星,永远不会发生碰撞。

示例 1:

1
2
3
4
5
输入:asteroids = [5,10,-5]

输出:[5,10]

解释:10 和 -5 碰撞后只剩下 10 5 10 永远不会发生碰撞。

示例 2:
1
2
3
4
5
输入:asteroids = [8,-8]

输出:[]

解释:8 和 -8 碰撞后,两者都发生爆炸。

示例 3:
1
2
3
4
5
输入:asteroids = [10,2,-5]

输出:[10]

解释:2 和 -5 发生碰撞后剩下 -5 。10 和 -5 发生碰撞后剩下 10 。

提示:

  • $2 <= asteroids.length <= 10^4$
  • $-1000 <= asteroids[i] <= 1000$
  • $asteroids[i] != 0$

模拟 + 栈

由于碰撞抵消总是从相邻行星之间发生,我们可以使用「栈」来模拟该过程。

从前往后处理所有的 $ats[i]$,使用栈存储当前未被抵消的行星,当栈顶元素方向往右,当前 $ats[i]$ 方向往左时,会发生抵消操作,抵消过程根据规则进行即可。

Java 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int[] asteroidCollision(int[] asteroids) {
Deque<Integer> d = new ArrayDeque<>();
for (int t : asteroids) {
boolean ok = true;
while (ok && !d.isEmpty() && d.peekLast() > 0 && t < 0) {
int a = d.peekLast(), b = -t;
if (a <= b) d.pollLast();
if (a >= b) ok = false;
}
if (ok) d.addLast(t);
}
int sz = d.size();
int[] ans = new int[sz];
while (!d.isEmpty()) ans[--sz] = d.pollLast();
return ans;
}
}

C++ 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
vector<int> asteroidCollision(vector<int>& asteroids) {
deque<int> d;
for (int t : asteroids) {
bool ok = true;
while (ok && !d.empty() && d.back() > 0 && t < 0) {
int a = d.back(), b = -t;
if (a <= b) d.pop_back();
if (a >= b) ok = false;
}
if (ok) d.push_back(t);
}
vector<int> ans(d.begin(), d.end());
return ans;
}
};

Python 3 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
def asteroidCollision(self, asteroids: List[int]) -> List[int]:
stk = []
for t in asteroids:
ok = True
while ok and stk and stk[-1] > 0 and t < 0:
a, b = stk[-1], -t
if a <= b:
stk.pop(-1)
if a >= b:
ok = False
if ok:
stk.append(t)
return stk

TypeScript 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
function asteroidCollision(asteroids: number[]): number[] {
const stk = new Array<number>()
for (const t of asteroids) {
let ok = true
while (ok && stk.length > 0 && stk[stk.length - 1] > 0 && t < 0) {
const a = stk[stk.length - 1], b = -t
if (a <= b) stk.pop()
if (a >= b) ok = false
}
if (ok) stk.push(t)
}
return stk
};

  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$

最后

这是我们「刷穿 LeetCode」系列文章的第 No.735 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!