Asteroid Collision
Problem statement
A row of asteroids is given as a list of non-zero integers. The absolute value is an asteroid's size and the sign is its direction: positive moves right, negative moves left. All asteroids move at the same speed.
When a right-moving asteroid meets a left-moving one, the smaller one explodes. If they are the same size, both explode. Asteroids moving in the same direction never meet, and a left-moving asteroid to the left of a right-moving one moves away from it.
Return the asteroids that are left once no more collisions can happen, in their original left-to-right order.
Examples
Example 1
Input: asteroids = [4, 9, -6]
Output: [4, 9]
Explanation: -6 hits 9 first. 9 is bigger, so -6 explodes and never reaches 4.
Example 2
Input: asteroids = [7, -7, -3, 2]
Output: [-3, 2]
Explanation: 7 and -7 are the same size and both explode. -3 then has nothing to its left moving right, and 2 moves away from it.
Hints
Approach
The survivors to the left of any point form a stack: the only one a new asteroid can hit is the last survivor.
- For each asteroid, if it moves right, or the stack is empty, or the top moves left, just push it. No collision is possible.
- If it moves left and the top moves right, they collide:
- top is smaller: pop it and check the next top with the same incoming asteroid;
- equal size: pop it, and the incoming one is also gone;
- top is bigger: the incoming one is gone.
- If the incoming asteroid survives all collisions, push it.
The stack, read bottom to top, is the answer. Every asteroid is pushed and popped at most once.
O(n)Space O(n)class Solution: def asteroidCollision(self, asteroids: list[int]) -> list[int]: stack = [] # survivors so far, left to right for rock in asteroids: alive = True while alive and rock < 0 and stack and stack[-1] > 0: if stack[-1] < -rock: # top is smaller: it explodes, keep checking stack.pop() elif stack[-1] == -rock: # same size: both explode stack.pop() alive = False else: # top is bigger: incoming one explodes alive = False if alive: stack.append(rock) return stackFollow-up questions
- Return how many collisions happened as well as the survivors.
- What changes if asteroids can have different speeds?
Frequently asked questions
The -2 moves left and the 1 moves right, so they move apart. A collision needs a positive value on the left and a negative value on the right.
One large left-moving asteroid can destroy several smaller right-movers in a row, as in [3, 5, -8]. It has to keep going until it is stopped or the stack runs out of right-movers.
It is a clean example of resolving events against the most recent unresolved item, which is the same shape as matching open and close events in a log or cancelling a queued deploy with a later rollback.