【双指针】:Leetcode283.移动零

朋友们、伙计们,我们又见面了,本专栏是关于各种算法的解析,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

目录

1. 双指针思想

2. 移动零

2.1 题目解析

2.2 算法思路

2.3 代码实现

2.4 算法复杂度


1. 双指针思想

常见的双指针有两种形式:一种是对撞指针、一种是快慢指针

1. 对撞指针:一般位于顺序结构中,也被称为左右指针。

  • 对撞指针从两端向中间移动,⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼近。
  • 对撞指针的终⽌条件⼀般是两个指针相撞或者错开(也可能在循环内部找到结果直接跳出循环),也就是:

                left==right(两个指针相撞)

                left>rigth(两个指针错开)

2. 快慢指针:⼜称为⻳兔赛跑算法,其基本思想就是使⽤两个移动速度不同的指针在数组或链表等序列结构上移动。

  • 这种⽅法对于处理环形链表或数组以及循环往复的问题⾮常有⽤。
  • 快慢指针的实现⽅式有很多种,最常⽤的⼀种就是:
  • 在⼀次循环中,每次让慢的指针向后移动⼀位,⽽快的指针往后移动两位,实现⼀快⼀慢。

2. 移动零

Leetcode283.移动零:https://leetcode.cn/problems/move-zeroes/

题目描述:

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

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

示例 1:

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

示例 2:

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

2.1 题目解析

根据题目描述,通过区间的划分对数组进行操作,可以简单的理解为将整个数组划分为两块,「数组分两块」是⾮常常⻅的⼀种题型,主要就是根据⼀种划分⽅式,将数组的内容分成左右两部分。这种类型的题,⼀般就是使⽤「双指针」来解决。

2.2 算法思路

解决本题使用的是双指针算法:

在这里为了方便,可以直接使用数组的下标来进行指针的模拟,要想对数组进行分块,首先设置一个指针(cur)对数组进行遍历,要将非0放到左边还需要一个指针(dest)来对数组进行区域划分,那么这两个指针的作用分别是:

cur:从左向右扫描,遍历整个数组。

dest:已处理区间内,非0元素的最后一个位置。

在遍历的整个过程中这两个指针会将数组分为三个区间:

如何实现呢?

首先让cur和dest都指向数组的起始位置(或者让dest指向-1的位置),然后让cur指针向后遍历,这时cur指针会遇到两种情况:

1. 遇到0时,直接++cur,继续向后面走。

2. 遇到非0时,需要交换dest位置与cur位置的元素,然后再将dest和cur加1。

结束的条件cur遍历完整个数组。

2.3 代码实现

使用最简单的循环语句即可完成遍历和判断:

class Solution 
{
public:
    void moveZeroes(vector<int>& nums) 
    {
        int cur = 0, dest = 0;
        for(;cur < nums.size(); cur++)
        {
            if(nums[cur])  //非0再交换
                swap(nums[dest++], nums[cur]);  //后置++,使用完了再++进行迭代
            //为0就继续向后面迭代
        }
    }
};

2.4 算法复杂度

该算法遍历一遍数组即可,时间复杂度:0(N)

没有开辟额空间,空间复杂度:O(1)

算法小总结:

数组分块,区间划分是在快速排序算法 中也有提到的,快速排序算法的关键就是进行区间的划分。

朋友们、伙计们,美好的时光总是短暂的,我们本期算法的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!  

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

stackY、

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

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

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

打赏作者

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

抵扣说明:

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

余额充值