力扣-283. 移动零

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的放在它右边,实现的原理就是使用了双指针
我们这里也可以模仿一下,设置中间值为0,若是大于等于0的数全部移到右边去(j负责维护大于0的数的数组下标, i负责维护所有等于0的数组坐标)

代码

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;      
          }
        }
    }
};
posted @ 2024-04-23 00:07  DawnTraveler  阅读(9)  评论(0编辑  收藏  举报