力扣-283. 移動零

DawnTraveler發表於2024-04-23

1.題目

題目地址(283. 移動零 - 力扣(LeetCode))

https://leetcode.cn/problems/move-zeroes/

題目描述

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

進階:你能儘量減少完成的操作次數嗎?

2.題解

2.1 雙指標法

思路

1.我們有可能會想到遍歷陣列,然後遇到0,刪除該元素,記錄個數count,最後在末尾補上count個零, 但是注意erase操作是要整體移動陣列的。 遍歷O(n) * 移動陣列O(n) = O(n^2)
2.

程式碼

  • 語言支援:C++

C++ Code:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int i = 0, j = 0;
        for(; i < nums.size(); i++){
            if(nums[i] != 0){
                nums[j] = nums[i];
                j++;
            }
        }
        for(; j < nums.size(); j++){
            nums[j] = 0;
        }
    }
};

複雜度分析

令 n 為陣列長度。

  • 時間複雜度:\(O(n)\)
  • 空間複雜度:\(O(n)\)

2.2 最佳化(快排)

思路

我們在第一個迴圈結束後,還需要再另起一個迴圈將值賦予0,能否在第一個迴圈同時完成聚集非零數和賦0的兩個操作?
在快排中,我們每次選取一箇中間值x, 將小於這個中間值x的數放到x左邊,大於這個中間值x的放在它右邊,實現的原理就是使用了雙指標
我們這裡也可以模仿一下

程式碼

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int i = 0, j = 0;
        for(; i < nums.size(); i++){
            if(nums[i] != 0){
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j++] = temp;      
          }
        }
    }
};

相關文章