Skip to content
DSAPrep

    ↑↓ to move · Enter to open · Esc to close

    MediumStack

    Asteroid Collision

    You are given an array asteroids of integers representing asteroids in a row. The indices of the asteroids 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 = [5,10,-5]

    Output: [5,10]

    Explanation: 10 and -5 collide, and 10 survives. 5 and 10 never collide.

    Example 2

    Input: asteroids = [8,-8]

    Output: []

    Explanation: 8 and -8 collide; equal sizes — both explode.

    Example 3

    Input: asteroids = [10,2,-5]

    Output: [10]

    Explanation: 2 and -5 collide, and -5 survives; then 10 and -5 collide, and 10 survives.

    Constraints

    • 2 <= asteroids.length <= 10^4
    • -1000 <= asteroids[i] <= 1000
    • asteroids[i] != 0
    View original on LeetCode ↗

    The collision rule has an order built into it. Two asteroids only ever fight when a left-mover (negative) has a right-mover (positive) somewhere to its left: two right-movers, two left-movers, or a left-mover standing to the left of a right-mover all cruise at the same speed and never touch. That means a right-mover can only be destroyed by a later left-mover, and a left-mover must engage the right-movers in front of it in left-to-right order — nearest one first. A stack captures exactly that chain: the top is always the nearest survivor, so it is always the next to fight.

    Brute Force: Repeated Passes

    Time O(n²)Space O(n)

    Apply the collision rule directly to the array, over and over. Sweep left to right; whenever two adjacent asteroids form a (right-mover, left-mover) pair, resolve the collision with the same size rules and consume both slots. Survivors go into a fresh array. One sweep is never enough: the survivor of a pair can become adjacent to a defender further left, forming a brand-new collision that only the next sweep sees. Keep sweeping until a full pass changes nothing.

    class Solution:
    def asteroidCollision(self, asteroids: list[int]) -> list[int]:
    changed = True
    while changed:
    changed = False
    nxt = []
    i = 0
    while i < len(asteroids):
    # A colliding pair is always "right-mover, then left-mover".
    if (
    i + 1 < len(asteroids)
    and asteroids[i] > 0
    and asteroids[i + 1] < 0
    ):
    left, right = asteroids[i], asteroids[i + 1]
    if left == -right: # equal sizes: both explode
    i += 2
    elif left > -right: # left survives: keep it
    nxt.append(left)
    i += 2
    else: # right survives: keep it
    nxt.append(right)
    i += 2
    changed = True
    else:
    nxt.append(asteroids[i])
    i += 1
    asteroids = nxt
    return asteroids

    Why it is quadratic: each sweep is O(n) work, but collisions can chain across sweeps. In the worst case a single big left-mover eats the right-movers one at a time — e.g. [10, 9, ..., 1, -100] advances the -100 one slot left per sweep — so the loop can run O(n) times for a total of O(n²). Rebuilding the array every pass also pays O(n) space per sweep.

    Stack Simulation

    OptimalTime O(n)Space O(n)

    Scan the array once. A right-mover cannot be hit from behind and cannot catch anything ahead, so push it and move on. A left-mover immediately goes to work, and the work is the whole algorithm: while the stack top is a weaker right-mover, pop it (it explodes) and keep resolving; if the top is equal, pop it and the incoming dies in the same round; if the top is stronger, the incoming explodes; and if the incoming outlasts the entire stack, push it — it becomes inert, since no later asteroid can ever catch a finished left-mover. Whatever remains in the stack, bottom to top, is the answer.

    class Solution:
    def asteroidCollision(self, asteroids: list[int]) -> list[int]:
    stack = []
    for a in asteroids:
    # Only a left-mover meeting a right-mover can collide.
    while stack and stack[-1] > 0 and a < 0:
    if stack[-1] == -a: # equal sizes: both explode
    stack.pop()
    a = 0
    elif stack[-1] < -a: # top is smaller: top explodes, keep resolving
    stack.pop()
    else: # top is bigger: incoming explodes
    a = 0
    if a != 0:
    stack.append(a)
    return stack

    Trace the file example, asteroids = [10, 2, -5] — the two-round cascade that shows why the while loop exists:

    start

    Input

    →10→2←5

    Stack

    empty

    Incoming

    —

    no collision this round

    collisions only happen when an incoming ← (negative) meets the top of the → (positive) stack — one while-loop round per top

    1 / 6
    currentseencomparingdiscardedresult

    Collision only when a left-mover (negative) meets a right-mover (positive) to its left. Scan left to right, keep alive right-movers in a stack, and let each arriving left-mover fight the top one at a time. The stack starts empty.

    Then asteroids = [8, -8] — the equal-size branch, where one round destroys both fighters:

    start

    Input

    →8←8

    Stack

    empty

    Incoming

    —

    no collision this round

    collisions only happen when an incoming ← (negative) meets the top of the → (positive) stack — one while-loop round per top

    1 / 4
    currentseencomparingdiscardedresult

    Second example, [8, -8]. 8 heads right from the earlier position, -8 heads left from the later one; equal speeds and equal distances put them head-on, so they meet in the middle.

    Why it is linear: every asteroid is pushed at most once and popped at most once — the cascade of pops is paid for by the elements it destroys — so the amortized work per asteroid is O(1), giving O(n) time overall. The stack is the output holder, so worst-case space is O(n) (e.g. every asteroid moving right). The survivors keep their original left-to-right order, so the stack is the answer as-is.

    More Stack practice