Medium草稿★★★★★O(n) 時間 · O(n) 空間
StackSimulation
Patterns🥞 堆疊🎮 模擬
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

735Asteroid CollisionStackMediumStack

給定整數陣列 asteroids 代表在同一列中的小行星。正數表示向右移動,負數表示向左移動,絕對值代表大小。兩個小行星相遇時,較小的會爆炸;若大小相同則同時爆炸。同方向的小行星永遠不會相遇。回傳碰撞後的狀態。

Example:

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

Intuition

TIP

核心思路:用堆疊處理碰撞,只有「棧頂向右、新元素向左」時才會發生碰撞,反覆比較直到碰撞結束。

Approaches

1. Array as Stack (no boxing) — O(n) / O(n)
  • Idea: 邏輯與堆疊解相同,改用 IntArray + top 指標,避免 ArrayDeque<Int> 裝箱
  • Time: O(n) - 每顆小行星最多進出一次
  • Space: O(n)
class Solution {
    fun asteroidCollision(asteroids: IntArray): IntArray {
        val st = IntArray(asteroids.size)
        var top = 0
        for (a in asteroids) {
            var alive = true
            while (alive && a < 0 && top > 0 && st[top - 1] > 0) {
                when {
                    st[top - 1] < -a -> top--                 // 棧頂較小,爆炸
                    st[top - 1] == -a -> { top--; alive = false }  // 同大同歸於盡
                    else -> alive = false                      // 棧頂較大,新的爆炸
                }
            }
            if (alive) st[top++] = a
        }
        return st.copyOf(top)
    }
}
⭐ 2. Stack Simulating Collisions — O(n) / O(n)
  • Idea: 遍歷小行星,正數直接 push。負數則與棧頂比較:棧頂較小就 pop 掉(繼續比較),棧頂較大就跳過新元素,一樣大就都移除
  • Time: O(n) - 每個小行星最多入棧出棧各一次
  • Space: O(n)
class Solution {
    fun asteroidCollision(asteroids: IntArray): IntArray {
        val stack = ArrayDeque<Int>()

        for (ast in asteroids) {
            var alive = true

            while (alive && ast < 0 && stack.isNotEmpty() && stack.last() > 0) {
                if (stack.last() < -ast) {
                    // 棧頂較小,爆炸
                    stack.removeLast()
                } else if (stack.last() == -ast) {
                    // 同大,同歸於盡
                    stack.removeLast()
                    alive = false
                } else {
                    // 棧頂較大,新的爆炸
                    alive = false
                }
            }

            if (alive) {
                stack.addLast(ast)
            }
        }

        return stack.toIntArray()
    }
}

🔑 Takeaways