735. Asteroid Collision - Explanation
Description
You are given an array asteroids of integers representing asteroids in a row. The indices of the asteriod in the array represent their relative position in space.
For each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed.
Find out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet.
Example 1:
Input: asteroids = [2,4,-4,-1]
Output: [2]Example 2:
Input: asteroids = [5,5]
Output: [5,5]Example 3:
Input: asteroids = [7,-3,9]
Output: [7,9]Constraints:
2 <= asteroids.length <= 10,000.-1000 <= asteroids[i] <= 1000asteroids[i] != 0
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Stack Data Structure - Understanding LIFO (Last In, First Out) operations: push, pop, peek
- Array Iteration - Processing elements sequentially from left to right
- Simulation Problems - Modeling real-world processes step by step in code
- Conditional Logic - Handling multiple cases based on element comparisons (direction and size)
1. Stack
Intuition
Collisions only happen when a right-moving asteroid (positive) meets a left-moving one (negative). A stack naturally models this: we process asteroids left to right, and when we see a negative asteroid, it can only collide with positive asteroids already on the stack. We keep popping and comparing until either the new asteroid is destroyed, destroys all opposing asteroids, or there are no more collisions possible.
Algorithm
- Initialize an empty stack.
- For each asteroid, if it's positive or the stack is empty or the top is negative, push it.
- If the asteroid is negative and the top is positive, compare sizes:
- If the top is smaller, pop it and continue checking.
- If they're equal, pop the top and discard the current asteroid.
- If the top is larger, discard the current asteroid.
- After processing all asteroids, the stack contains the survivors.
class Solution:
def asteroidCollision(self, asteroids: List[int]) -> List[int]:
stack = []
for a in asteroids:
while stack and a < 0 and stack[-1] > 0:
diff = a + stack[-1]
if diff < 0:
stack.pop()
elif diff > 0:
a = 0
else:
a = 0
stack.pop()
if a:
stack.append(a)
return stackTime & Space Complexity
- Time complexity:
- Space complexity:
2. Without Stack
Intuition
We can simulate the stack behavior using the input array itself. We maintain a pointer j that tracks the "top" of our virtual stack within the array. When collisions occur, we decrement j (like popping). Surviving asteroids are written to position j + 1. This gives us O(1) extra space while maintaining the same logic.
Algorithm
- Use pointer
j = -1to represent an empty stack. - For each asteroid, handle collisions by comparing with
asteroids[j]when both are in opposite directions. - If the current asteroid survives, increment
jand store it atasteroids[j]. - If destroyed, skip storing it.
- Return the subarray from index
0toj(inclusive).
class Solution:
def asteroidCollision(self, asteroids: List[int]) -> List[int]:
n = len(asteroids)
j = -1
for a in asteroids:
while j >= 0 and asteroids[j] > 0 and a < 0:
if asteroids[j] > abs(a):
a = 0
break
elif asteroids[j] == abs(a):
j -= 1
a = 0
break
else:
j -= 1
if a:
j += 1
asteroids[j] = a
return asteroids[:j + 1]Time & Space Complexity
- Time complexity:
- Space complexity: for the output array.
Common Pitfalls
Assuming All Asteroids Collide
Not all asteroids collide. Two asteroids moving in the same direction (both positive or both negative) never collide. A negative asteroid followed by a positive asteroid also never collide since they move apart.
# Wrong: checking if signs differ without considering direction
if asteroids[i] * asteroids[j] < 0: # collision!
# Right: collision only when positive is before negative
if stack[-1] > 0 and a < 0: # potential collisionForgetting Chain Reactions
A single incoming asteroid can destroy multiple asteroids on the stack. You need a loop, not just a single comparison.
# Wrong: only one comparison
if stack and a < 0 and stack[-1] > 0:
# handle one collision and move on
# Right: keep checking until no more collisions
while stack and a < 0 and stack[-1] > 0:
# handle collision, may need to pop multiple timesIncorrect Size Comparison
When comparing asteroid sizes, remember that negative asteroids have negative values. Use absolute value for size comparison.
# Wrong: comparing raw values
if stack[-1] > a: # incorrect when a is negative
# Right: compare magnitudes
if stack[-1] > abs(a): # or equivalently: stack[-1] + a > 0
Sign in to join the discussion