Move Zeroes

題目描述

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

輸入:nums = [0,1,0,3,12]
輸出:[1,3,12,0,0]

輸入:nums = [0]
輸出:[0]

解題思路

1

初始化

slow = 0,指向下一個非零元素應該放置的位置

2

遍歷

fast 用 for 迴圈從 0 到 n-1 逐一掃描每個元素

3

搬移

若 nums[fast] != 0,執行 swap(nums[slow], nums[fast]),然後 slow++。交換把非零值搬到前面,零被推到後面

4

結束

遍歷完成後,nums[0..slow-1] 全是非零且保持原順序,nums[slow..n-1] 全是零

程式碼

C#

csharp
public class Solution {
    public void MoveZeroes(int[] nums) {
        int slow = 0;
        for (int fast = 0; fast < nums.Length; fast++) {
            if (nums[fast] != 0) {
                // 交換:非零元素往前搬
                (nums[slow], nums[fast]) = (nums[fast], nums[slow]);
                slow++;
            }
        }
    }
}

TypeScript

typescript
function moveZeroes(nums: number[]): void {
    let slow = 0;
    for (let fast = 0; fast < nums.length; fast++) {
        if (nums[fast] !== 0) {
            [nums[slow], nums[fast]] = [nums[fast], nums[slow]];
            slow++;
        }
    }
}

Python

python
def moveZeroes(nums: list[int]) -> None:
    slow = 0
    for fast in range(len(nums)):
        if nums[fast] != 0:
            nums[slow], nums[fast] = nums[fast], nums[slow]
            slow += 1

複雜度分析

| | Time | Space | |--|------|-------| | 本解法 | O(n) | O(1) |

fast 從 0 到 n-1 只走一遍 O(n),每步做常數次操作。原地交換不需額外陣列,空間 O(1)。

邊界情況

圖解

[0,1,0,3,12]
slow=0
fast=1: swap → [1,0,0,3,12]
slow=1
fast=3: swap → [1,3,0,0,12]
slow=2
fast=4: swap → [1,3,12,0,0]
完成
[1,3,12,0,0]

圖表展示交換過程:fast=0 時值為 0 跳過,fast=1 時值為 1 與 slow=0 交換。fast=2 時值為 0 跳過,fast=3 時值為 3 與 slow=1 交換。每次交換後 slow 前進一格,零被自然推到後方。

進階觀點

💡面試追問

  • Q: 為什麼用交換而不是直接覆蓋再補零? A: 兩種都可以,都是 O(n)。覆蓋法需要兩次遍歷:第一次把非零值依序寫入 nums[0..slow-1],第二次把 nums[slow..n-1] 全部填 0。交換法只需一次遍歷,因為 swap 同時完成「搬前」和「補零」兩個動作,操作次數更少。

  • Q: 如果要保持零的位置不變,移動非零元素? A: 題意完全不同。需要找出零的位置形成「空隙」,然後把非零值重新排列填入非空隙位置。本質上變成 partition 問題,需要額外記錄零的位置。

  • Q: 快慢指針模式還能用在哪? A: LeetCode 27(Remove Element)用相同框架移除指定值。LeetCode 26(Remove Duplicates from Sorted Array)用 slow 追蹤不重複的寫入位置。鏈表中快慢指針用於找中點(slow 走一步、fast 走兩步)和 Floyd 環檢測。

理解測驗

🤔 為什麼交換而非覆蓋更優雅?

🤔 slow 指針代表什麼含義?

你可能也想看

443. String Compression392. Is Subsequence

按 ← → 鍵切換課程