每日一练【移动零】

一、题目描述

283. 移动零 - 力扣(LeetCode)

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

每日一练【移动零】_第1张图片

二、题目解析

可以将本题划分为数组划分(数组分块)的一类题。

一般这类题可以运用双指针的思路去解决。

注意这里的指针并不是真正的指针,而是利用数组下标来充当指针

两个指针的作用:

  • cur:从左到右扫描数组,遍历数组
  • dest:已经处理的区间内,非零元素的最后一个位置(所以初始要置为-1)

所以这两个指针可以把数组分为三个区间

每日一练【移动零】_第2张图片

那这两个指针是如何做到的呢?

cur从前往后遍历的过程中:

  1. 遇到0元素:cur++
  2. 遇到非零元素:

swap(dest+1,cur);然后dest和cur分别++,继续遍历。

注意快排中的双指针算法也是运用这一思想!!!

三、原码

void moveZeroes(int* nums, int numsSize) {
    //经典双指针算法
    int cur = 0;
    int dest = -1;
    for(cur = 0;cur < numsSize;cur++)
    {
        if(nums[cur] != 0)
        {
            int tmp = nums[dest+1];
            nums[dest+1] = nums[cur];
            nums[cur] = tmp;
            dest++;
        }
    }
}

四、复杂度

本题运用了双指针的算法,时间复杂度是O(N),因为cur指针遍历数组一遍,就已经按照题目要求排好序了。

空间复杂度是O(1),本题没有额外开辟数组空间。

总结,双指针算法解决数组数组划分问题,无论是时间复杂度还是空间复杂度,算法都是最优的!

你可能感兴趣的:(C语言/C++练习题,算法,数据结构)