力扣之移動零

水冗水孚發表於2022-07-14

題目描述

給定一個陣列 nums,編寫一個函式將所有 0 移動到陣列的末尾,同時保持非零元素的相對順序。

請注意 ,必須在不復制陣列的情況下原地對陣列進行操作。

示例 1:

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

示例 2:

輸入: nums = [0]
輸出: [0]
力扣原題目地址:https://leetcode.cn/problems/...

思路分析

解法一 遍歷統計0出現了幾次並刪除之,最後根據0出現的次數往尾部追加0

var moveZeroes = function (nums) {
    let count = 0 // 1. 定義一個變數,用來統計0出現的次數
    for (let i = 0; i < nums.length; i++) { // 2. 遍歷這個陣列,看看0出現了幾次
        if (nums[i] == 0) { // 3. 如果遇到的不是0,不做任何操作;如果遇到0了,就把0刪掉
            nums.splice(i, 1) // 4. 把遇到的這一項(0)給刪除掉
            i-- // 5. 注意 陣列塌陷,索引統一往前平移一位
            count = count + 1 // 6. 然後統計一下0出現的次數
        }
    }
    for (let i = 0; i < count; i++) { // 7. 根據0出現的次數,決定往陣列的尾部追加幾個0
        nums.push(0) // 8. 出現了幾個0,最後就追加幾個0,
    }
};

這種方式,需要遍歷兩次,我們遍歷一次也是可以解決的,思路略有相似。如下程式碼

解法二 尾部追加一個結束項標識,遍歷遇到0刪除之

 var moveZeroes = function (nums) {
    nums.push('endFlag') // 1. 手動在陣列的最後,追加一項,用於判斷是否遍歷到最後的標識
    for (let i = 0; i < nums.length; i++) { // 2. 遍歷這個陣列
        // 3. 一開始肯定不是最後一項的標識,所以繼續往後看
        if (nums[i] == 'endFlag') { // 8. 當遇到之前我們手動新增的'endFlag'標識的時候,就說明原來的陣列遍歷一遍了
            nums.splice(i, 1) // 9. 最後再把之前手動新增的標識給刪掉就行啦,搞定
            return
        }
        if (nums[i] === 0) { // 4. 當遇到0的時候做移動零操作
            nums[nums.length] = 0 // 5. 先再陣列的最後的位置新增一個0
            nums.splice(i, 1) // 6. 然後在把當前的0刪除掉,這樣也可以理解為移動0
            i-- // 7. 注意陣列刪除掉一個元素以後,陣列的索引塌陷,後續的索引都會往前進一位,所以需要再統一扣除1位,以達到平衡
        }
    }
};

總結

在實際工作中,時間複雜度,要優先與空間複雜度,因為空間複雜度問題,多增加點記憶體就行了。但是時間複雜度,才是我們寫程式碼追求的極速目標。所以,能遍歷一次的,最好不要遍歷兩次。至於多定義幾個變數導致多用了一些記憶體,基本上可以忽略的

相關文章