当前位置: 首页 > news >正文

双指针专题(一):其实是“覆盖”元素——「移除元素」

欢迎来到双指针专题第一篇!

场景想象:你手里有一叠扑克牌(数组),里面混进去了几张“鬼牌”(需要移除的元素val)。

  • 暴力做法:每看到一张鬼牌,把它抽出来,然后把后面所有的牌往前挪一格填补空缺。

  • 双指针做法:如果不想要鬼牌,我们根本不用“抽”它。我们只需要把好牌一张张地往前挪,把鬼牌的位置给覆盖掉就行了。

力扣 27. 移除元素

https://leetcode.cn/problems/remove-element/

题目分析:

  • 输入:数组nums,值val

  • 目标原地移除所有数值等于val的元素。

  • 输出:返回移除后数组的新长度k

  • 要求:空间复杂度必须是 O(1)。

例子:nums = [3, 2, 2, 3], val = 3

  • 结果:k = 2,nums的前两个元素应该是[2, 2]。后面剩啥无所谓。

核心思维:快慢指针 (Fast & Slow Pointers)

我们定义两个指针:

  1. 快指针 (fast)探路者。它的任务是遍历数组,寻找新数组里需要的元素(即不等于val的元素)。

  2. 慢指针 (slow)建筑师。它指向下一个新元素应该存放的位置

操作逻辑:

  • fast指针在前面跑,如果nums[fast]是“鬼牌”(等于val):

    • fast继续往前跑,忽略它(相当于直接跳过)。

  • 如果nums[fast]是“好牌”(不等于val):

    • 把这张好牌拿过来,覆盖到slow指向的位置:nums[slow] = nums[fast]

    • 然后slow向前走一步,准备接下一张好牌。

  • 最后,slow的数值就是新数组的长度。

为什么不用splice

作为前端,我们太熟悉nums.splice(i, 1)了。 但是,splice的底层实现是把删除位置后面的所有元素都往前挪一位。这是一个 O(N) 的操作。 如果你在for循环里用splice,那就是 O(N2) 的复杂度。 而双指针法只需要遍历一次,复杂度是O(N)

代码实现 (JavaScript)

JavaScript

/** * @param {number[]} nums * @param {number} val * @return {number} */ var removeElement = function(nums, val) { // 慢指针:指向下一个“好元素”应该存放的位置 let slow = 0; // 快指针:负责遍历数组,寻找“好元素” for (let fast = 0; fast < nums.length; fast++) { // 如果快指针找到的不是目标值(是好元素) if (nums[fast] !== val) { // 把它挪到慢指针的位置(覆盖旧数据) nums[slow] = nums[fast]; // 慢指针向前一步,准备接下一个 slow++; } // 如果 nums[fast] === val,那就什么都不做 // 快指针会自动 fast++ 跳过它,慢指针原地不动 } // 此时 slow 的值,刚好就是新数组的长度 return slow; };

深度模拟

nums = [0, 1, 2, 2, 3, 0, 4, 2],val = 2

  1. fast=0(0): 不是2。填入nums[0],slow变 1。 ([0...])

  2. fast=1(1): 不是2。填入nums[1],slow变 2。 ([0, 1...])

  3. fast=2(2): 是2!跳过。slow还是 2。

  4. fast=3(2): 是2!跳过。slow还是 2。

  5. fast=4(3): 不是2。填入nums[2],slow变 3。 ([0, 1, 3...])

    • 注意:原来的23覆盖了。

  6. ...以此类推。

总结

这道题是双指针最基础的应用——原地操作数组。 记住这个口诀:快指针找,慢指针填。

这种“覆盖”的思想在后面很多题目(比如“移动零”、“删除有序数组重复项”)中都会用到,是必须掌握的肌肉记忆。


下一题预告:有序数组的平方

好了,热身结束。下一题我们稍微加点难度。

  • 给你一个按非递减顺序排序的整数数组[-4, -1, 0, 3, 10]

  • 要求返回每个数字的平方组成的新数组,也要按非递减顺序排序。

  • 输出:[0, 1, 9, 16, 100]

难点在于:负数平方后可能变得很大。最大的数可能在最左边(负数),也可能在最右边(正数)。 这时候,如果还在用快慢指针从一头往另一头跑,肯定不行。我们需要两个指针,分别站在数组的两头,像决斗一样向中间逼近。

准备好迎接**“左右指针”**的挑战了吗?

http://www.jsqmd.com/news/176733/

相关文章:

  • vue基于springboot的中国山川教学网站
  • 双指针专题(二):两头堵的智慧——「有序数组的平方」
  • 持续性能测试:DevOps流水线中的关键一环
  • 2025年终AI智能床垫品牌推荐:基于权威榜单与用户口碑的TOP5排名揭晓。 - 十大品牌推荐
  • 双指针专题(三):去重的艺术——「三数之和」
  • vue基于springboot的指数基金数据分析系统
  • 2025年终中老年人智能床垫品牌推荐:聚焦健康监测功能的5强榜单深度解析。 - 十大品牌推荐
  • vue基于springboot的智能旅游推荐系统
  • 2025年聚焦:哪些盐水注射机公司赢得了市场好口碑?盐水注射机口碑排行综合实力与口碑权威评选 - 品牌推荐师
  • DroidCam局域网传输优化:提升手机到PC的稳定性实战案例
  • 如何为长辈挑选智能床垫?2025年终最新品牌综合评测及5款推荐! - 十大品牌推荐
  • 2025年终中老年人智能床垫品牌推荐:聚焦健康监测功能的5强品牌深度解析 - 十大品牌推荐
  • RK3588平台下aarch64与设备树交互机制深度解析
  • 2025年汽配采购必看:周边双主轴排刀机工厂推荐,刀塔机/46排刀机/Y轴/动力刀塔/双主轴/刀塔车床/三轴机排刀机定制推荐排行 - 品牌推荐师
  • lut调色包下载站点整合?视觉生成模型色彩校准新方向
  • paqsp.dll文件损坏丢失找不到 打不开程序 下载方法
  • vue基于springboot的信息技术论坛
  • 中老年人智能床垫哪个品牌更可靠?2025年终5大品牌横向评测与最终推荐! - 十大品牌推荐
  • GPTQ训练支持:逐层量化与误差补偿机制解析
  • 序列分类模型训练指南:情感分析与意图识别任务实战
  • 深度测评10个AI论文网站,MBA论文写作必备!
  • Megatron并行加速CPT/SFT/DPO全流程:200+模型已验证
  • GRPO训练方法详解:多模态场景下的强化学习优化策略
  • 如何为家中长者选择智能床垫?2025年终五大品牌横向评测及最终推荐! - 十大品牌推荐
  • C语言数据读写性能提升10倍的秘密(存算一体设计精髓)
  • 【专家级调优经验】:基于OpenMP 5.3的多核任务分配性能翻倍秘技
  • C语言如何精准调用汇编代码?昇腾算子库开发者必须掌握的3个关键点
  • 继续训练量化模型:BNB/AWQ/GPTQ是否可微调?
  • vue基于springboot的学生成绩管理系统
  • OpenAI接口兼容性测试:无缝迁移现有应用的可行性分析