news 2026/4/23 12:48:22

简单理解:双指针移动0

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
简单理解:双指针移动0

先明确核心目标

这段代码要实现的功能是:把一个数组里的所有 0 都移到数组末尾,非 0 元素保持原来的先后顺序。比如:输入[0,1,0,3,12]→ 输出[1,3,12,0,0]

先拆解最容易懂的部分:swap 交换函数

void swap(int *a, int *b) { // 定义交换函数,a和b是两个整数的"地址" int t = *a; // *a表示"取地址a里的值",先把a地址的值存到临时变量t *a = *b, *b = t; // 把b地址的值放到a地址,再把t的值放到b地址(完成交换) }

大白话解释

  • 你可以把int *a理解成 “一张纸条,上面写着一个整数的家庭住址”;
  • *a就是 “根据这个住址找到对应的人,拿到他手里的数字”;
  • 整个 swap 函数就是:先记下来 A 家的数字,再把 B 家的数字放到 A 家,最后把记下来的数字放到 B 家 → 完成两个数字的交换。

举个例子:如果a是数组第 0 个元素的地址(值是 0),b是数组第 1 个元素的地址(值是 1),调用swap(a,b)后,两个位置的值就变成 1 和 0 了。

重点拆解:moveZeroes 核心函数(双指针法)

先记住两个指针的 “分工”:

  • left 指针:“搬运工”,负责标记「下一个非 0 元素应该放到哪个位置」;
  • right 指针:“侦察兵”,负责遍历数组,找非 0 元素。
void moveZeroes(int *nums, int numsSize) { // nums是数组地址,numsSize是数组长度 int left = 0, right = 0; // 两个指针都从数组第0个位置(最左边)出发 while (right < numsSize) { // 侦察兵没走到数组末尾,就一直找 if (nums[right]) { // 如果侦察兵找到的元素不是0(非0值在C里算"真") swap(nums + left, nums + right); // 把这个非0元素搬到搬运工的位置 left++; // 搬运工往右走一步,准备接下一个非0元素 } right++; // 侦察兵不管找没找到,都往右走一步继续找 } }

用具体例子模拟执行(最关键!)

我们用nums = [0,1,0,3,12]numsSize = 5来一步步走:

步骤right 指针位置nums [right] 值是否非 0执行操作left 指针位置数组变化
100只走 right0[0,1,0,3,12]
211交换 left (0) 和 right (1),left+11[1,0,0,3,12]
320只走 right1[1,0,0,3,12]
433交换 left (1) 和 right (3),left+12[1,3,0,0,12]
5412交换 left (2) 和 right (4),left+13[1,3,12,0,0]
65-退出循环-3最终结果 [1,3,12,0,0]

大白话复盘这个过程

  1. 侦察兵 right 先看第 0 个位置(0),是 0,直接往前走;
  2. 侦察兵到第 1 个位置(1),不是 0 → 喊搬运工 left(在 0 位置)过来交换,交换后 left 走到 1 位置,right 继续走;
  3. 侦察兵到第 2 个位置(0),是 0,直接往前走;
  4. 侦察兵到第 3 个位置(3),不是 0 → 喊搬运工 left(在 1 位置)过来交换,交换后 left 走到 2 位置,right 继续走;
  5. 侦察兵到第 4 个位置(12),不是 0 → 喊搬运工 left(在 2 位置)过来交换,交换后 left 走到 3 位置,right 走到 5(超出数组长度),循环结束;
  6. 最终 left 指针走过的位置都是非 0 元素,剩下的位置自然都是 0。

补充解释两个容易懵的点

  1. nums + left是什么意思?
    • nums是数组第一个元素的地址,nums + left就是 “从数组开头往后数 left 个位置的地址”;
    • 比如nums + 0= 数组第 0 个元素的地址,nums + 1= 数组第 1 个元素的地址,等价于&nums[left]
  2. if (nums[right])为什么能判断非 0?
    • 在 C 语言里,布尔判断中:0 = 假,非 0(不管是 1、3、12)= 真;
    • 所以if (nums[right])等价于if (nums[right] != 0),只是简写而已。

总结

  1. swap 函数:通过 “地址” 交换两个数字,核心是*符号能 “取地址里的值”;
  2. 双指针分工:right(侦察兵)找非 0 元素,left(搬运工)负责放非 0 元素;
  3. 核心逻辑:侦察兵找到非 0 元素,就和搬运工交换位置,搬运工再往前走,最终所有非 0 元素都被搬到左边,0 自然留在右边。

先明确核心概念:数组名nums的本质

在 C 语言里,数组名nums本身就是一个指针,它指向数组第一个元素的地址(可以理解成 “数组的家门牌”)。比如数组nums = [0,1,0,3,12]

  • nums→ 等价于&nums[0]→ 指向第 0 个元素(0)的地址;
  • nums[0]→ 取第 0 个元素的值(0);
  • nums[1]→ 取第 1 个元素的值(1)。

关键:nums + left是什么?

nums + left指针的算术运算,意思是:从数组的起始地址(nums)往后 “走left步”,指向数组第left个元素的地址。

  • 等价于&nums[left]&是取地址符号);
  • 比如left=0nums+0=&nums[0](第 0 个元素地址);
  • 比如left=1nums+1=&nums[1](第 1 个元素地址);
  • 比如left=2nums+2=&nums[2](第 2 个元素地址)。

结合代码场景理解

代码里调用swap(nums + left, nums + right),本质是:

  1. 拿到nums数组中第left个元素的地址(nums+left);
  2. 拿到nums数组中第right个元素的地址(nums+right);
  3. 把这两个地址传给swap函数,交换这两个地址对应的值。

用具体例子落地

还是用nums = [0,1,0,3,12],当left=0right=1时:

  • nums + left=nums+0=&nums[0]→ 第 0 个元素(0)的地址;
  • nums + right=nums+1=&nums[1]→ 第 1 个元素(1)的地址;
  • 调用swap后,这两个地址的值被交换,数组变成[1,0,0,3,12]

再比如left=1right=3时:

  • nums+1=&nums[1](值为 0);
  • nums+3=&nums[3](值为 3);
  • 交换后数组变成[1,3,0,0,12]

为什么不用&nums[left]反而用nums+left

两者效果完全一样,只是写法不同:

  • &nums[left]是 “数组下标写法”,更直观,新手容易懂;
  • nums+left是 “指针算术写法”,是 C 语言更底层的写法,很多程序员习惯这么写;
  • 你把代码里的nums+left换成&nums[left],功能完全不变。

总结

  1. nums + left等价于&nums[left],都是取数组第left个元素的地址
  2. 传给swap函数的必须是 “地址”(指针),因为swap需要通过地址修改原数组的值;
  3. 指针算术nums+left的核心是:从数组起始地址往后偏移left个元素的位置。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:36:58

新华社发布:中国AI,最新趋势来了!

Datawhale干货 最新&#xff1a;2026 趋势&#xff0c;来源&#xff1a;新华社新华深读&#xff5c;2026年中国AI发展趋势前瞻人工智能&#xff08;AI&#xff09;企业数量超过6000家&#xff0c;AI核心产业规模预计突破1.2万亿元&#xff0c;同比增长近30%&#xff1b;国产开源…

作者头像 李华
网站建设 2026/4/23 11:36:28

3PEAK思瑞浦 TP1561AL1-S5TR-S SOT23-5 运算放大器

特性 供电电压:2.5伏至6伏低供电电流:每通道600微安(典型值) 轨到轨输入和输出 带宽:6MHz(典型值) 斜率:4.5V/us(典型值) 优异的EMI抑制性能偏移电压:士3mV(最大值) 偏移电压温度漂移:1uV/C(典型值)低噪声:在1kHz时为19nV/vHz(典型值)高输出能力:100毫安(典型值)工作温度范围:-…

作者头像 李华
网站建设 2026/4/11 1:45:38

还是智能的悲剧:达沃斯论坛赫拉利的观点分析

以下是针对2026年达沃斯论坛中尤瓦尔赫拉利&#xff08;Yuval Noah Harari&#xff09;关于人工智能的核心观点的深度分析&#xff0c;结合其著作 《人类简史》与 《智人之上》中的思想框架&#xff0c;从文明预警视角展开&#xff1a;一、AI的“代理化”与人类控制权的消解赫拉…

作者头像 李华
网站建设 2026/4/23 12:20:41

uniapp+python微信小程序的在线问诊挂号开药系统

文章目录系统概述技术架构核心功能安全与合规应用场景扩展性系统设计与实现的思路主要技术与实现手段源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统概述 基于UniApp和Python的微信小程序在线问诊挂号开药系统&#xff0c;整合了移动…

作者头像 李华
网站建设 2026/4/23 10:44:22

Java实习模拟面试之Java基础篇(1-8题):高频核心考点深度解析

Java实习模拟面试之Java基础篇&#xff08;1-8题&#xff09;&#xff1a;高频核心考点深度解析适合人群&#xff1a;准备Java后端实习/校招的同学 关键词&#xff1a;Java基础、面试八股文、 vs equals、引用类型、泛型擦除、反射优化、序列化 字数&#xff1a;约3500字 | 阅读…

作者头像 李华
网站建设 2026/4/23 10:45:55

【2026】 LLM 大模型系统学习指南 (35)

Diffusion Model&#xff1a;从噪声到图像的生成魔法 —— 核心原理与入门实操 Diffusion Model&#xff08;扩散模型&#xff09;是当前最主流的生成模型之一&#xff0c;核心逻辑是 “逐步加噪再逐步去噪”—— 先把清晰图像变成纯噪声&#xff0c;再训练模型学习 “反向去噪…

作者头像 李华