算法双指针系列-Day1-移动零


前言

最近估计会多写一些算法题目的文章,我也是刚开始学习,写的文章就当记录寒假生活了。如果有初学算法的小伙伴我们可以一起学习,还是新手,有错误的话,还请指正,感谢。
最近就先写双指针类问题了,我使用的编程语言为C++,每个题目我会附上力扣的链接,在文章最后会附上C++代码和Java代码。


一、题目链接

移动零

二、题目描述

题⽬描述:
给定⼀个数组 nums ,编写⼀个函数将所有 0 移动到数组的末尾,同时保持⾮零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进⾏操作。
示例 1:
输⼊: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
⽰例 2:
输⼊: nums = [0]
输出: [0]


三、算法思路

1.初步分析

分析可知,该题目就是想要通过对给定的数组进行操作,最终把这个数组分为两部分,前一部分是非0值,后一部分全都是0.
此处我们可以使用一个cur指针来遍历数组(注意双指针的含义不是非得是指针才行,这里我们对数组进行操作,通过cur指针遍历数组,实际上就是通过下标来遍历嘛,所以这里的指针指代的实际上就是下标),再利用一个dest指针来记录非零元素序列的最后⼀个位置。根据 cur 在扫描的过程中,遇到的不同情况,分类处理,实现数组的划分。在 cur 遍历期间,使 [0, dest] 的元素全部都是非零元素, [dest + 1, cur - 1] 的元素全是零。
最终结果如图所示
在这里插入图片描述
下标 [0, dest]的元素全为非零元素, [dest + 1, cur - 1] 的元素全是零。

2.更进一步

这里我们刚开始将cur指针初始化为0,因为要遍历数组嘛,数组下标就是从0开始的,然后把dest初始化为-1,因为cur还没开始遍历,所以非零元素相当于没有,那就赋值为-1了。之后cur开始一个一个遍历,如果下标为cur的元素为0,那就直接cur++,如果不是0,那就先让dest++,然后再将++过后的dest指向的元素与cur指向的元素互换,达到将非零元素换到前面去的目的,重复上述操作直到cur遍历完整个数组。那么是不是非零元素就全被换到了前面,而零元素就全在后面了呢。
举例
这里以输⼊:nums = [0,1,0,3,12]为例讲解
一开始dest=-1,cur=0,首元素为0,cur++后cur为1,1处元素非0,那就dest++后dest为0,互换后数组变为了 [1,0,0,3,12]。之后cur++后cur为2,2处元素为0,cur直接++变为3,3处元素为非零,那就dest++后dest为1,将下标为1和3的元素互换,此时数组为[1,3,0,0,12]。cur++后cur为4,元素非零,dest先++后dest为2,互换后数组为[1,3,12,0,0]。cur再++后cur为5,已经遍历完数组,结束。
整体过程:
[0,1,0,3,12]
[1,0,0,3,12]
[1,3,0,0,12]
[1,3,12,0,0]
至此我们达到了题目的要求,不知各位是否理解了。

3.代码编写

遍历我们用个for循环,很容易解决,元素互换我们可以直接使用C++中自带的swap函数,每次互换前先要dest加1才能互换。所以我们可以用++dest,这就会导致dest会先自增再使用。
以下是C++代码:

class Solution {
public:
    void moveZeroes(vector<int>& nums) 
    {
        for(int cur = 0, dest = -1; cur < nums.size(); cur++)
        if(nums[cur]) // 处理⾮零元素
        swap(nums[++dest], nums[cur]);

    }
};

在这里插入图片描述
这是运行结果,至于所用时间什么的话,大家不用在意,你多运行几次会发现时间时好时坏。
这里是Java代码:

class Solution
{
 public void moveZeroes(int[] nums)
 {
     for(int cur = 0, dest = -1; cur < nums.length; cur++)
     if(nums[cur] != 0) // 仅需处理⾮零元素
     {
          dest++; // dest 先向后移动⼀位
          // 交换
          int tmp = nums[cur];
          nums[cur] = nums[dest];
          nums[dest] = tmp;
     }

 }
}

四、复杂度

时间复杂度:
我们这里就是在不断遍历数组的过程中,以中间的0作为分割,然后左侧是非0元素,右侧是未处理的元素。在处理的过程中我们只是遍历了一次这个数组,所以复杂度为 O ( n )
空间复杂度:
在本题中我们并没有去开出额外的空间,所以复杂度为 O ( 1 )

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

争不过朝夕,又念着往昔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值