LeetCode - 283. 移動零 swift

原題鏈接:
https://leetcode-cn.com/problems/move-zeroes/

給定一個數(shù)組 nums,編寫一個函數(shù)將所有 0 移動到數(shù)組的末尾,同時保持非零元素的相對順序。

示例:

輸入: [0,1,0,3,12]
輸出: [1,3,12,0,0]
說明:

必須在原數(shù)組上操作,不能拷貝額外的數(shù)組。
盡量減少操作次數(shù)。

算法

/**
簡單粗暴的一種解題方法,類似于冒泡排序
兩次遍歷。每次遍歷前后元素比較,前一個為0,后一個不為0則交換,遍歷完成之后,會有一個為0的元素到數(shù)組的最后一個位置,然后進行下一次遍歷,直到所有元素遍歷完成。所有為0的元素都放在數(shù)組最后。
 時間復(fù)雜度 O(n^2)
 空間復(fù)雜度 O(1)
 提交LeetCode時不通過,因為數(shù)據(jù)量太大時耗時太多
*/
func moveZeroes(_ nums: inout [Int]) {
    for i in 0..<nums.count {
        for j in stride(from: i+1, to: nums.count, by: 1) {
            if nums[i] == 0 && nums[j] != 0 {
                let temp = nums[i]
                nums[i] = nums[j]
                nums[j] = temp
            }
        }
    }
}
/**
 輸入:[0,1,0,3,12]
 每次交換的結(jié)果:
 [1, 0, 0, 3, 12]
 [1, 0, 0, 3, 12]
 [1, 0, 0, 3, 12]
 [1, 0, 0, 3, 12]
 [1, 0, 0, 3, 12]
 [1, 3, 0, 0, 12]
 [1, 3, 0, 0, 12]
 [1, 3, 0, 0, 12]
 [1, 3, 12, 0, 0]
 [1, 3, 12, 0, 0]
 */
/**
 時間復(fù)雜度O(n)
 空間復(fù)雜度O(1)
 快慢指針
 i : 快指針
 lastNonZeroIndex : 慢指針(最后一個非零指針)
 第一次遍歷,向前移動所有的非零數(shù)字,慢指針之前都是非零,之后都是零
 第二次遍歷,慢指針之后的數(shù)字賦值為零
 */
func moveZeroes(_ nums: inout [Int]) {
    var lastNonZeroIndex = 0
    for i in 0..<nums.count {
        if nums[i] != 0 {
            // 向前移動非零數(shù)字
            nums[lastNonZeroIndex] = nums[i]
            // 最后非零指針向后移動一位
            lastNonZeroIndex = lastNonZeroIndex + 1
        }
    }
    // 以上遍歷完成之后,lastNonZeroIndex之前的數(shù)字都是非零,之后的數(shù)字都是0
    // 再次遍歷,將lastNonZeroIndex之后的元素全部賦值為0
    for i in lastNonZeroIndex..<nums.count {
        nums[i] = 0
    }
}
??動畫演示
/**
 時間復(fù)雜度O(n)
 空間復(fù)雜度O(1)
 快慢指針
 進一步優(yōu)化
 類似快速排序,將0作為中間的數(shù)字進行左右分割,等于0的元素放在右邊,不等于0的元素放在左邊。
 */
func moveZeroes(_ nums: inout [Int]) {
    var lastNonZeroIndex = 0
    for i in 0..<nums.count {
        if nums[i] != 0 {
            // 直接進行交換
            let temp = nums[lastNonZeroIndex]
            nums[lastNonZeroIndex] = nums[i]
            nums[i] = temp
            // 交換也可以這么寫
            //    (nums[i], nums[lastNonZeroIndex]) = (nums[lastNonZeroIndex], nums[i])

            lastNonZeroIndex = lastNonZeroIndex + 1
        }
    }
}
??動畫演示
/**
 時間復(fù)雜度O(n)
 空間復(fù)雜度O(1)
 快慢指針
 參考了國際站的題解之后在上一個基礎(chǔ)上再次優(yōu)化
 */
func moveZeroes(_ nums: inout [Int]) {
    // 過濾掉不需要處理的情況
    // 數(shù)組元素小于2個,直接返回
    guard nums.count > 1 else {
        return
    }
    var lastNonZeroIndex = 0
    for i in 0..<nums.count {
        if nums[i] != 0 {
            if i > lastNonZeroIndex {
                // 通過以上 i > lastNonZeroIndex 避免了兩個 i == lastNonZeroIndex 時的冗余操作
                // 交換 改為 賦值,非零數(shù)字賦值到零數(shù)字的位置,之前非零的位置可以直接賦值為零(交換也是賦值為零,所以直接進行賦值零)
                nums[lastNonZeroIndex] = nums[i]
                nums[i] = 0
            }
            // 非零就后移一位
            lastNonZeroIndex += 1
        }
    }
}

var nums = [0,1,0,3,12]
moveZeroes(&nums)

以上算法的一步步優(yōu)化參考了中文站和國際站上的一些題解。
LeetCode上有一位同學(xué)的題解非常好,比官方的題解更容易理解。鏈接:https://leetcode-cn.com/problems/move-zeroes/solution/dong-hua-yan-shi-283yi-dong-ling-by-wang_ni_ma/
以上的動畫演示都是出自這位同學(xué)的題解,如有侵權(quán),請聯(lián)系刪除。

GitHub:https://github.com/huxq-coder/LeetCode
歡迎star

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容