Description

給定整數陣列 nums,將所有 0 移到陣列末尾,同時保持非零元素的相對順序。必須原地操作。

Example:

Input: nums = [0,1,0,3,12] Output: [1,3,12,0,0]

Intuition#

核心思路:用一個慢指針記錄下一個非零元素該放的位置,快指針掃描所有元素。

  • 類似「移除特定元素」的模式(LC 27 Remove Element)
  • 慢指針維護「已處理區域」的尾端,快指針不斷找非零元素往前搬
  • 最後慢指針之後的位置全部填 0

Approaches#

1: 額外陣列#

  • 概念: 建立新陣列,先放非零元素,再補 0
  • 時間複雜度: O(n)
  • 空間複雜度: O(n)
額外陣列程式碼
class Solution {
    fun moveZeroes(nums: IntArray): Unit {
        val result = IntArray(nums.size)
        var idx = 0
        for (num in nums) {
            if (num != 0) result[idx++] = num
        }
        for (i in nums.indices) nums[i] = result[i]
    }
}

⭐2: Two Pointers(快慢指針)#

  • 概念: 慢指針 slow 追蹤下一個非零元素的位置,快指針 fast 掃描整個陣列,遇到非零就交換到 slow 位置
  • 時間複雜度: O(n) - 一次遍歷
  • 空間複雜度: O(1) - 原地操作
class Solution {
    fun moveZeroes(nums: IntArray): Unit {
        var slow = 0
        for (fast in nums.indices) {
            if (nums[fast] != 0) {
                val temp = nums[slow]
                nums[slow] = nums[fast]
                nums[fast] = temp
                slow++
            }
        }
    }
}

使用交換而非覆蓋(先寫非零再補零),可以在一次遍歷中完成,不需要第二次迴圈填零。

🔑 Takeaways#

  • Pattern: 快慢指針分區(類似 partition),慢指針維護「已處理」邊界
  • 關鍵技巧: 與 LC 27 Remove Element 同一模板;交換比覆蓋更優雅,一次遍歷搞定