跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C算法

双指针算法实战:移动零与复写零

双指针是处理数组问题的常用技巧。移动零题目中,使用快慢指针将非零元素前移;复写零题目中,为避免覆盖未处理元素,采用从后向前遍历的策略。两者均满足原地修改要求,时间复杂度为 O(n),适合面试高频考察场景。

SparkGeek发布于 2026/3/28更新于 2026/6/1418 浏览
双指针算法实战:移动零与复写零

在学习了基础语法之后,是时候通过实际题目来巩固一下双指针技巧了。今天我们来拆解两道经典的数组原地操作题:移动零与复写零。

一、移动零

题目描述

给定一个数组 nums,要求将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。注意,必须在原数组上操作,不能创建新数组。

思路解析

这道题的核心在于如何在不破坏原有顺序的前提下完成交换。最直观的想法是创建一个新数组,但这违反了空间复杂度的要求。

我们可以使用两个指针:

  • current(快指针):负责遍历整个数组,寻找非零元素。
  • dest(慢指针):指向当前应该放置非零元素的位置。

当 current 遇到非零元素时,将其与 dest 位置的元素交换,然后 dest 向后移动一位。无论是否交换,current 都会继续向前。这样就能保证所有非零元素按顺序被'挤'到前面,剩下的位置自然就是 0。

代码实现

void Swap(int *a, int *b) {
    int temp = 0;
    temp = *a;
    *a = *b;
    *b = temp;
}

void moveZeroes(int* nums, int numsSize) {
    int current = 0;
    int dest = 0;
    while (current < numsSize) {
        if (nums[current] != 0) {
            Swap(nums + dest, nums + current);
            dest++;
        }
        current++;
    }
}

这段逻辑在力扣等平台上提交均能通过。关键点在于 Swap 函数保证了非零元素的相对顺序不被打乱。

二、复写零

题目描述

给定一个固定长度的整数数组 arr,将数组中出现的每个 0 都复写一遍,其余元素向右移动。超出数组长度的元素将被丢弃。

思路解析

如果从前往后遍历并插入 0,后面的元素会被不断覆盖,导致数据丢失。因此,正确的策略是从后往前处理。

具体步骤如下:

  1. 确定写入边界:先遍历一次数组,计算如果进行复写操作,最后一个有效元素会落在哪里。这决定了我们倒序复制的起始点。
  2. 处理边界情况:如果最后一个被复写的元素恰好是 0,且它会导致数组越界(即原本该位置是 0,复写后多出一个 0),则需要特殊处理,丢弃末尾的一个元素。
  3. 倒序复制:从确定的边界开始,向前遍历原数组。遇到 0 就写入两次,遇到非零元素则写入一次。

代码实现

void duplicateZeros(int* arr, int arrSize) {
    // 第一步:找出最后被复写到的位置
    int cur = 0;
    int dest = -1;
    while (cur < arrSize) {
        if (arr[cur]) {
            dest++;
        } else {
            dest += 2;
        }
        if (dest >= arrSize - 1) break;
        cur++;
    }

    // 判断边界情况:如果倒数第二个元素是 0,会导致多出一个 0 被截断
    if (dest == arrSize) {
        arr[arrSize - 1] = 0;
        cur--;
        dest -= 2;
    }

    // 第二步:从后向前实现复写操作
    while (cur >= 0) {
        if (arr[cur] == 0) {
            arr[dest--] = 0;
            arr[dest--] = 0;
        } else {
            arr[dest--] = arr[cur];
        }
        cur--;
    }
}

通过这种倒序填充的方式,我们完全避免了覆盖尚未处理的元素,确保了算法的正确性和效率。

目录

  1. 一、移动零
  2. 题目描述
  3. 思路解析
  4. 代码实现
  5. 二、复写零
  6. 题目描述
  7. 思路解析
  8. 代码实现
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 二分查找实战:山峰数组峰顶索引与寻找峰值
  • OpenClaw 掀起 AI 智能体革命:百度腾讯布局与能力分析
  • 二分查找算法详解与经典例题解析
  • SpringBoot 多级缓存实战:Redis 与 Caffeine 结合优化 API 性能
  • FMC 与 FMC+ 标准详解及引脚定义
  • 轻量级C++ GIF动画生成库实战指南
  • Java 环境搭建与首个 Hello World 程序实战
  • C/C++ 轻量级搜索引擎实战:正/倒排索引构建
  • 微服务项目在线 OJ 系统基于 Java Spring 的 Token 与身份认证实现
  • Python 虚拟环境搭建与 PyCharm 配置实战
  • voidImageViewer:支持 GIF/WebP 动图的轻量级看图工具
  • MiniOneRec 框架解析:基于 LLM 的生成式推荐系统实践
  • 宇树机器人 G1 二次开发:基于 FAST_LIO 的建图与 RViz 配置
  • WebMCP:浏览器原生 AI 交互新范式
  • 利用 VR-Reversal 将 3D 视频转换为普通格式
  • Java 接入阿里百炼大模型实战指南
  • 基于FPGA的FIR数字滤波器设计(Quartus与Vivado实现)
  • Spring Cloud LoadBalancer 负载均衡实战与原理
  • Stable Diffusion 3.5 FP8 多卡并行实测:双 GPU 扩展性分析
  • Flutter 在 OpenHarmony 中集成 objectid 实现离线分布式 ID 生成

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online