【LeetCode】283. Move Zeroes(移动零)-C++实现及其3种优化方法

问题描述:

一、常规解法

(1) 基本实现思路

先将数组中非零的元素取出来:

然后将非零元素放回到数组中:

 

 最后将剩余的元素赋予0:

(2)代码实现

// 时间复杂度: O(n)
// 空间复杂度: O(n)
class Solution {
public:
    void moveZeroes(vector<int>& nums) {

        vector<int> nonZeroElements; 

        // 将vec中所有非0元素放入nonZeroElements中
        for(int i = 0 ; i < nums.size() ; i ++)
            if(nums[i])
                nonZeroElements.push_back(nums[i]);

        // 将nonZeroElements中的所有元素依次放入到nums开始的位置
        for(int i = 0 ; i < nonZeroElements.size() ; i ++)
            nums[i] = nonZeroElements[i];

        // 将nums剩余的位置放置为0
        for(int i = nonZeroElements.size() ; i < nums.size() ; i ++)
            nums[i] = 0;
    }
};

int main() {

    int arr[] = {0, 1, 0, 3, 12};
    vector<int> vec(arr, arr + sizeof(arr)/sizeof(int));

    Solution().moveZeroes(vec);

    for(int i = 0 ; i < vec.size() ; i ++)
        cout << vec[i] << " ";
    cout << endl;

    return 0;
}

 二、第一种优化方法

(1)基本思路

1.将蓝色箭头设为k,红色箭头设为i:

2.k=0,遍历i,如果num[i]>0,nums[k] = nums[i];

然后k++,i++

        for(int i = 0 ; i < nums.size() ; i ++)
            if(nums[i])
                nums[k++] = nums[i];

                                                            ----------------------------------------------------------- 

                                                              --------------------------------

                                                           ------------------------------------------------

(2)当i = nums.size(),将nums剩余的位置放置为0

-----------------------------------------------------

这一部分代码:

        // 将nums剩余的位置放置为0
        for(int i = k ; i < nums.size() ; i ++)
            nums[i] = 0;

 (3)第一种优化方法的完整代码实现

class Solution {
public:
    void moveZeroes(vector<int>& nums) {

        int k = 0; // nums中, [0...k)的元素均为非0元素

        // 遍历到第i个元素后,保证[0...i]中所有非0元素
        // 都按照顺序排列在[0...k)中
        for(int i = 0 ; i < nums.size() ; i ++)
            if(nums[i])
                nums[k++] = nums[i];

        // 将nums剩余的位置放置为0
        for(int i = k ; i < nums.size() ; i ++)
            nums[i] = 0;
    }
};

 三、第二种优化方法

第一种优化的方法需要我们去补充最后的两个0,那么我们能不能当遍历完成,0自动在数组的后面?

(1)

当k=0,i=1时,num[1] = 1,非0,此时我们swap(nums[k] , nums[i]);

然后k++:

 ------------------------------------

-------------------------------

 --------------------------

(2)当i = 3,k = 2时,我们swap(nums[k] , nums[i]);

--------------------------------------

--------------------- 

 

(3)第二种优化方法完整代码实现:

// 原地(in place)解决该问题
// 时间复杂度: O(n)
// 空间复杂度: O(1)
class Solution {
public:
    void moveZeroes(vector<int>& nums) {

        int k = 0; // nums中, [0...k)的元素均为非0元素

        // 遍历到第i个元素后,保证[0...i]中所有非0元素
        // 都按照顺序排列在[0...k)中
        // 同时, [k...i] 为 0
        for(int i = 0 ; i < nums.size() ; i ++)
            if(nums[i])
                swap(nums[k++] , nums[i]);

    }
};

四、第三种优化方法 

(1)在第二种方法中,当数组中所有元素都非0时,每一次循环都会自己和自己交换,

所以,如果i = k时,我们直接k++即可;

当i!= k时,我们在调用swap(nums[k++] , nums[i])

(2)第三种优化方法代码完整实现:

// 原地(in place)解决该问题
// 时间复杂度: O(n)
// 空间复杂度: O(1)
class Solution {
public:
    void moveZeroes(vector<int>& nums) {

        int k = 0; // nums中, [0...k)的元素均为非0元素

        // 遍历到第i个元素后,保证[0...i]中所有非0元素
        // 都按照顺序排列在[0...k)中
        // 同时, [k...i] 为 0
        for(int i = 0 ; i < nums.size() ; i ++)
            if(nums[i])
                if(k != i)
                    swap(nums[k++] , nums[i]);
                else
                    k ++;
    }
};

参考资料:

https://coding.imooc.com/class/chapter/82.html#Anchor

猜你喜欢

转载自blog.csdn.net/qq_40416052/article/details/81947849