LeetCode每日一题之 复写0

目录

题目介绍:

算法原理:

特殊位置处理:

代码实现:


题目介绍:

题目链接:. - 力扣(LeetCode)

算法原理:

这种对数组元素进行修改,移动的题目我们仍然可以使用双指针法,不过我们按照常规思路从左到右处理数组,不难发现如下这种问题:

当cur指向1时,让dest下一个元素复写cur指向的元素,并让dest和cur++,当cur指向0的时候, 让dest后两个元素复写0,并让cur++,dest+=2。按照这种常规思路,模拟运行几步就会发现问题:

当cur指向第一个0时,会让后面的2被0复写,这样就会导致未处理的数就会被覆盖 。那么如何解决这个问题呢?

当双指针算法可能会覆盖未处理数据时,我们不妨倒着来遍历数组,假设我们两根指针都已找到了结束位置(如何找到等会会讲)

 此时,我们再像刚才那样:

若cur指向的元素不为0,则让dest指向的元素复写cur指向的元素,再cur--,dest--,若cur指向的元素为0,则让dest指向的元素复写0,再dest--,继续让dest指向的元素复写0,最后让dest--,cur--。

这样之后确实能像我们预想一样处理完数组,那么现在最重要的问题来了,就是,如何让两个指针找到结束位置。其实很简单,只要把上面讲的常规思路稍作修改,只移动指针,不复写数据,当dest走到数组末尾的时候结束:

初始位置如下:

当cur找到非0时,dest++,cur++。

当cur找到0时,dest+=2,cur++。

当dest走到数组末尾时结束。 

这样走完后,我们的两个指针就会走到对应结束的位置。

特殊位置处理:

上面的算法看似完美,实则还有一个特殊情况没处理,当执行如下案例时:

在找结束位置算法中,两个指针走到如上图所示的位置时,此时cur指向0,dest走两个位置后

可以发现dest越界了,我们再像之前讲的那样复写时,会出现越界访问,所以要特殊处理一下:

  当cur 和 dest 找到结束位置后,判断dest是否等于n(数组元素个数),若等于则是出现了这种情况,我们就用一个if 自己控制第一步复写,然后再让复写算法用循环走剩下的,第一步复写:先--dest,再让dest指向的元素复写cur指向的元素,再dest--,cur--,第一步复写后指针位置如图:

代码实现:

void duplicateZeros(int* arr, int arrSize) {
    int dest =-1;
    int cur =0;
    int n =arrSize;
    //找到结束位置
    while(dest<n-1)
    {
        if(arr[cur]==0)
        {
            dest+=2;
        }
        else
        {
            dest++;
        }
        if(dest<n-1)
        {
           cur++;
        }
    }
    //特殊位置处理
    if(dest==n)
    {
        dest--;
        arr[dest]=arr[cur];
        dest--;
        cur--;
    }
    //开始从后往前进行复写
    while(cur>=0)
    {
        if(arr[cur]==0)
        {
            arr[dest]=0;
            --dest;
            arr[dest]=0;
            --dest;
        }
        else
        {
            arr[dest]=arr[cur];
            --dest;
        }
        cur--;
    }
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咬_咬

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

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

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

打赏作者

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

抵扣说明:

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

余额充值