双指针——复写零

文章介绍了如何使用暴力枚举和双指针方法解决数组中就地复制0的问题,暴力枚举方法在最坏情况下时间复杂度为O(n^2),而双指针优化后的时间复杂度降低至O(n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

题目链接

复写零
在这里插入图片描述
看到这道题的第一眼,就会感觉,太简单了,但不要忽略题目的一个要求,要就地操作,如果不就地操作,直接遍历一遍将结果写到另外一个数组就完成了。

算法原理

暴力枚举

从头到尾模拟一遍,如果找到0则先让0后的数整体往后挪一位,然后增加一位0,注意这个新增的0不要再计算!如此反复,最后跑到末尾即可!

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int n = arr.size() - 1;
        for (int i = 0; i <= n; i++) {
            if (arr[i] == 0 && i + 1 <= n) {
                for (int j = n; j - 1 > i; j--) {
                    arr[j] = arr[j - 1];
                }
                arr[++i] = 0;
            }
        }
    }
};

在最坏的情况下,全是0,那么这个时候的时间复杂度就是O(n^2)

在这里插入图片描述

双指针

定义两个指针
dest:表示最终的位置
cur:从左往右扫描数组,遍历数组
先模拟异地操作,然后由异地操作优化未就地操作
在这里插入图片描述
从前往后原地操作,当走到0的时候,0后面的数字就被覆盖了
在这里插入图片描述
这时候就要考虑一下,既然异地当复写0的时候最后几个元素是会被淘汰掉的,那么从后面的位置开始向前复写就可以了,由上面的异地模拟可以得出[1,0,0,3,0,4,5,0]的4这个位置就是最后一个复写的数字,
我们再从后往前模拟一遍原地操作
在这里插入图片描述

编写代码逻辑如下在这里插入图片描述

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

这里有一个特殊情况
在这里插入图片描述

代码

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cur = 0, dest = -1, n = arr.size();
        // 找到cur和dest的最后位置
        while (cur < n) {
            if (arr[cur])
                dest++;
            else
                dest += 2;
            if (dest >= n - 1)
                break;
            cur++;
        }
        if (dest == n) {
            arr[n - 1] = 0;
            cur--;
            dest -= 2;
        }
        //  从后往前开始复写0
        while (cur >= 0) {
            if (arr[cur])
                arr[dest--] = arr[cur--];
            else {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }
        }
    }
};

相比暴力解法,这里的时间复杂度只有O(n)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

晚安刘十三

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

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

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

打赏作者

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

抵扣说明:

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

余额充值