【优选算法】专题1 -- 双指针 -- 复写0

这篇具有很好参考价值的文章主要介绍了【优选算法】专题1 -- 双指针 -- 复写0。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:

补充一下前文没有写到的双指针入门知识:专题1 -- 双指针 -- 移动零

目录

基础入门知识:

1. 复写零(easy)

1. 题⽬链接:1089.复习0 - 力扣(LeetCode)

2. 题⽬描述:

3.算法原理:

异地操作

本地操作

【从后向前的复写过程】

整体思路:

🎯1.先找到最后一个“复写”的数;

1.5 处理一下边界情况:

📌2."从后向前"完成复写操作(前面已经验证)


基础入门知识:

的双指针有两种形式,种是对撞指针种是左右指针

对撞指针⼀般⽤于顺序结构中,也称左右指针

• 对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼近。

• 对撞指针的终⽌条件⼀般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循环),也就是:

◦ left == right (两个指针指向同⼀个位置)

◦ left > right (两个指针错开)

快慢指针:⼜称为⻳兔赛跑算法

其基本思想:就是使⽤两个📌移动速度📌不同的指针在数组或链表等序列结构上移动。

💨这种⽅法对于处理环形链表或数组⾮常有⽤。

其实不单单是环形链表或者是数组,⭕如果我们要研究的问题出现循环往复的情况时,均可考虑使⽤快慢指针的思想。

📍快慢指针的实现⽅式有很多种,最常⽤的⼀种就是:

• 在⼀次循环中,每次让慢的指针向后移动⼀位,⽽快的指针往后移动两位,实现⼀快⼀慢

1. 复写零(easy)

1. 题⽬链接:1089.复习0 - 力扣(LeetCode)

2. 题⽬描述:

给你度固定的整数数组 arr ,请你将该数组中出现的每个零都复写遍,并将其余的元素向右平移。

注意:请不要在超过该数组度的位置写元素。请对输的数组就地进上述修改,不要从函数返回任何东西。

例 1:

arr = [1,0,2,3,0,4,5,0]

输出: [1,0,0,2,3,0,0,4]

解释:

函数后,输的数组将被修改为: [1,0,0,2,3,0,0,4]

3.算法原理:

这题需要用到双指针算法,但这不是凭空来的,原题目需要我们对原数组进行操作,

异地操作

📚但是为了方便如何理解复写 0 的过程,我们先画出异地操作的过程:

原图:

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

复写过程:

cur用于遍历原数组,dest指向了异地操作的数组

当cur指向的元素为非0时,dest此时要复写一次cur指向的非0元素,cur++,dest++

当cur指向的元素为 时,dest要先复写一次0,之后dest++,再复写一次0,复写两次完毕之后cur++,dest++

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

复写完成:

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

本地操作

优化为本地操作后,尝试从前往后操作:

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

如果「从前向后」进⾏原地复写操作的话,由于 0 的出现会复写两次导致没有复写的数「被覆
盖掉」。

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

验证【从后往前】操作的可行性:

因此我们选择「从后往前」的复写策略,cur指向最后一个需要复写的元素,dest指向最后一个需要复写的位置(结果中的最后一个位置)  

这同时也是上面异地操作的结果:

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

【从后向前的复写过程】

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

结果:我们可以看到,原地操作和异地操作最终的复写结果是一样的

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

        在这个示例里面,我们可以看到cur指向的4是最后一个需要复写的元素,但是在其他示例里面我们不清楚,那么我们如何找到最后一个需要复写的元素呢?

整体思路:

🎯1.先找到最后一个“复写”的数;

1.先判断 cur 位置的值
2.决定 dest 向后移动一步或者两步
3.判断一下 dest 是否已经到结束为止
4.cur++;

开始的状态:

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

遍历过程(动图实现):【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

最终的状态:

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

但是思考一下,此时如果cur指向的数组倒数第二个元素是0,那么dest此时指向的位置将会是数组最后一个元素的位置的下一个位置,因为上面遍历的方式是遇到 0 则++两次,非0是一次,那么必定会造成数组越界:【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

1.5 处理一下边界情况:

arr[n - 1] = 0;

cur--;

dest -= 2;

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

📌2."从后向前"完成复写操作(前面已经验证)

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode

代码实现:

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
    int cur = 0,dest = -1,n=arr.size();
    
    //1.先找到最后一个需要复写的数
    while(cur<n)
    {
        if(arr[cur])
            dest++;
        else
            dest+=2;
        if(dest>=n-1)//数组最后一个位置或者最后一个位置的下个位置
            break;
        cur++;
        }
    //2.处理一下边界情况
    if(dest == n)
    {
        arr[n-1] = 0;
        cur--;
        dest-=2;
    }
    //3.从后往前完成复写操作
    while(cur >= 0)
    {
        if(arr[cur])
        {
           arr[dest--] = arr[cur--];
           //arr[dest] = arr[cur],cur--,dest--
        }
        else
        {
           arr[dest--] = 0;
           arr[dest--] = 0;
           cur--;
        }
    }
    }
};

【优选算法】专题1 -- 双指针 -- 复写0,优选算法篇,算法,c++,c语言,编程语言,leetcode 

本篇完结。 

🔧本文修改次数:0

🧭更新时间:2024年3月26日  文章来源地址https://www.toymoban.com/news/detail-854624.html

到了这里,关于【优选算法】专题1 -- 双指针 -- 复写0的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【算法优选】双指针专题——贰

    常⻅的双指针有两种形式,⼀种是 对撞指针 ,⼀种是 左右指针 对撞指针 :⼀般⽤于顺序结构中,也称左右指针。 对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼近。 对撞指针的终⽌条件⼀般是两个指针相遇或者错开(也可能

    2024年02月08日
    浏览(51)
  • 算法初阶双指针+C语言期末考试之编程题加强训练

    常⻅的双指针有两种形式,⼀种是对撞指针,⼀种是左右指针。 对撞指针:⼀般⽤于顺序结构中,也称左右指针。 • 对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼 近。 • 对撞指针的终⽌条件⼀般是两个指针相遇或者错开(

    2024年02月05日
    浏览(50)
  • 【编程语言 · C语言 · 函数指针】

    由于指针可以指向任何存储器位置中的地址,因此它们也可以指向可执行代码的开头。 函数指针或函数指针指向内存中函数的可执行代码。函数指针可以存储在数组中,也可以作为参数传递给其他函数。 函数指针声明使用 * 就像使用任何指针一样: (*func_name)  周围的括号很

    2024年02月10日
    浏览(55)
  • Rust编程语言入门之智能指针

    指针:一个变量在内存中包含的是一个地址(指向其它数据) Rust 中最常见的指针就是”引用“ 引用: 使用 借用它指向的值 没有其余开销 最常见的指针类型 智能指针是这样一些数据结构: 行为和指针相似 有额外的元数据和功能 通过记录所有者的数量,使一份数据被多个

    2023年04月16日
    浏览(49)
  • 深入浅出 C 语言:学变量、掌控流程、玩指针,全方位掌握 C 编程技能

    C 语言介绍 C 语言的特性 C 语言相对于其他语言的优势 C 程序的编译 C 中的 Hello World 程序 参考文章: C 语言入门:如何编写 Hello World C 语言函数:入门指南 C 中的变量和 C 语言中的作用域规则 C 中的数据类型 运算符及其类型 C 语言中的类型转换 参考文章: C 语言注释

    2024年02月02日
    浏览(44)
  • c语言编程中出现错误: 表达式必须包含指向对象的指针类型。 该错误如何解决? 下文解答

    表达式必须包含指向对象的指针类型,但他具有类型\\\"int\\\" 具体原因是因为arr数组本质是一个指针类型,指向的是首元素的地址,如果用int 来接收显然不合适,以至于在引用下列定义的int类型的变量时候产生错误——表达式必须包含指向对象的指针类型,但他具有类型\\\"int\\\",解决

    2024年02月11日
    浏览(46)
  • 【算法】活用双指针完成复写零操作

    Problem: 1089. 复写零 首先我们来分析一下本题的题目意思 可以看到题目中给到了一个数组,意思是让我们将数组中的零元素都复写一遍,然后将其余的元素向后平移 光就上面这样来看还是不太形象,我们通过画图来分析一下,通过下图我们可以看到,凡是0的都复写了两遍,凡

    2024年02月11日
    浏览(53)
  • 【算法优选】 二分查找专题——贰

    二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用 顺序存储结构 ,而且表中元素按 有序排列 。 查找过程 : 首先,假设表中元素是按升序排列,将表中间位置记录的与查找比较,如果两者相等,

    2024年02月08日
    浏览(43)
  • 【算法优选】 二分查找专题——壹

    二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用 顺序存储结构 ,而且表中元素按 有序排列 。 查找过程 : 首先,假设表中元素是按升序排列,将表中间位置记录的与查找比较,如果两者相等,

    2024年02月08日
    浏览(46)
  • 【算法优选】前缀和专题——叁

    含义 : 前缀和实际上就是对于长度为n的数组, 我们新建立一个数组长度为n+1,第i个元素的值为前i个元素的和(包括第i个元素) 。 特点 : 前缀和数组比原数组多一个长度。 前缀和的第0个元素的值为0。 根据前缀和数组的特点,求前缀和时。我们只需要用第i个元素的值

    2024年02月06日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包