735. Asteroid Collision - Explanation

Problem Link

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] <= 1000
  • asteroids[i] != 0


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



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

  1. Initialize an empty stack.
  2. For each asteroid, if it's positive or the stack is empty or the top is negative, push it.
  3. 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.
  4. 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 stack

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n)

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

  1. Use pointer j = -1 to represent an empty stack.
  2. For each asteroid, handle collisions by comparing with asteroids[j] when both are in opposite directions.
  3. If the current asteroid survives, increment j and store it at asteroids[j].
  4. If destroyed, skip storing it.
  5. Return the subarray from index 0 to j (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: O(n)O(n)
  • Space complexity: O(n)O(n) 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 collision

Forgetting 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 times

Incorrect 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