【双指针】复写零

一、题目

给你一个长度固定的整数数组 arr,将每个出现的零复写一遍,并右移其余元素。要求:

  • 不能在数组长度外写入元素
  • 必须原地修改数组,不能使用额外数组

示例

输入:arr = [1,0,2,3,0,4,5,0]

输出:[1,0,0,2,3,0,0,4](最后一个0因数组长度限制无法复写)

二、解题思路:双指针从后往前填充

如果直接从前往后遍历复写零,会覆盖后续未处理的元素;如果用额外数组存储结果,又不符合"原地修改"的要求。

因此我们采用先找边界、再从后往前填充的双指针策略:

  1. 第一步:确定有效元素的边界

    • 用指针 cur 遍历原数组,dest 模拟"复写零后"的数组长度(遇到非零元素,dest+1;遇到零,dest+2)。
    • dest 超过数组长度时,停止遍历。此时 cur 左侧的元素是最终数组需要包含的元素。
  2. 第二步:处理边界溢出情况

    • dest == n(数组长度),说明最后一个元素是零且复写后超出长度,此时只需要写一个零到数组末尾。
  3. 第三步:从后往前填充数组

    • cur 位置倒序遍历,将元素写入 dest 位置:非零元素直接写,零则写两次(注意 dest 指针同步左移)。

三、完整代码

cpp 复制代码
class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cur = 0;    // 遍历原数组的指针
        int dest = -1;  // 模拟复写零后的数组长度指针
        int n = arr.size();

        // 第一步:找到有效元素的边界(cur左侧元素是最终数组需要包含的元素)
        while (cur < n) {
            if (arr[cur] != 0) {
                dest++;  // 非零元素,dest+1
            } else {
                dest += 2; // 零元素,复写后占两个位置,dest+2
            }
            if (dest >= n - 1) { // 当dest到达数组末尾(或超出),停止遍历
                break;
            }
            cur++;
        }

        // 第二步:处理dest刚好等于n的情况(最后一个零复写后超出数组长度)
        if (dest == n) {
            dest--;          // 回退到数组最后一个位置
            arr[dest--] = 0; // 只写一个零
            cur--;           // cur指针回退
        }

        // 第三步:从后往前填充数组
        while (cur >= 0) {
            if (arr[cur] != 0) {
                arr[dest--] = arr[cur]; // 非零元素直接填充
            } else {
                arr[dest--] = 0;        // 零元素填充两次
                arr[dest--] = 0;
            }
            cur--;
        }
    }
};

四、复杂度分析

  • 时间复杂度:O(n)。只需要遍历数组两次(一次找边界,一次填充),n是数组长度。
  • 空间复杂度:O(1)。只使用了常量级别的额外变量,完全原地修改。
相关推荐
Figo_Cheung1 天前
Figo关于热、声、光的物理本质辨析——从根本上解释了光速的恒定性与声速的介质依赖性,揭示了光热转换的微观场论机制
算法·机器学习
青桔柠薯片1 天前
数据结构:排序与算法
数据结构·排序算法
格林威1 天前
Baumer相机轴承滚珠缺失检测:用于精密装配验证的 6 个核心算法,附 OpenCV+Halcon 实战代码!
人工智能·opencv·算法·计算机视觉·视觉检测·工业相机·堡盟相机
一起养小猫1 天前
Flutter for OpenHarmony 实战:2048游戏算法与优化深度解析
算法·flutter·游戏
执着2591 天前
力扣hot100 - 226、翻转二叉树
数据结构·算法·leetcode
-Try hard-1 天前
排序和查找算法:插入排序、希尔排序、快速排序以及二分查找
数据结构·算法·排序算法
Ivanqhz1 天前
向量化计算
开发语言·c++·后端·算法·支持向量机·rust
ffqws_1 天前
进阶搜索:迭代加深搜索(IDS)埃及分数题解
算法·迭代加深
格林威1 天前
相机的“对焦”和“变焦”,这二者有什么区别?
开发语言·人工智能·数码相机·opencv·算法·计算机视觉·视觉检测
LXS_3571 天前
常用算法(下)---拷贝、替换、算术生成、集合算法
开发语言·c++·算法·学习方法