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

【LeetCode 27. 移除元素】C++ 范围 for 极简实现与原理解析

【LeetCode 27. 移除元素】C++ 范围 for 极简实现与原理解析

本文将详细讲解 LeetCode 第 27 题「移除元素」的高效解法,重点介绍如何使用 C++11 范围 for 循环实现原地修改,并深入分析其原理与性能优势。


一、题目回顾

给你一个数组nums和一个值val,你需要原地移除所有数值等于val的元素。元素的顺序可能发生改变。然后返回nums中与val不同的元素的数量。

  • 要求:原地修改数组,使前k个元素为有效元素,其余元素无需关心。
  • 返回值:有效元素的数量k

示例:

  • 输入:nums = [3,2,2,3],val = 3
  • 输出:2,数组前两位变为[2,2]

二、核心思路:双指针法

这道题的经典解法是双指针法

  • 用一个慢指针k记录有效元素的存放位置
  • 遍历数组,遇到不等于val的元素,就将其写入nums[k],并将k后移。
  • 遍历结束后,k即为有效元素的数量,数组前k位就是结果。

为什么用范围 for?

传统写法需要手动管理索引,而 C++11 引入的范围 for 循环可以更简洁地遍历容器,代码可读性更高,且不易出错。在本题中,范围 for 可以完美替代传统索引遍历,实现极简代码。


三、代码实现(范围 for 版本)

class Solution { public: int removeElement(vector<int>& nums, int val) { int k = 0; // 慢指针,记录有效元素位置 // 范围for遍历所有元素 for (auto x : nums) { if (x != val) { nums[k++] = x; // 写入有效元素,指针后移 } } return k; // 返回有效元素数量 } };

代码解析

  1. 参数传递vector<int>& nums是引用传递,保证函数内修改直接作用于原数组。
  2. 慢指针k:初始为 0,每次遇到有效元素就写入当前位置,然后自增。
  3. 范围 forfor (auto x : nums)会自动遍历nums中的每个元素,x是当前元素的拷贝(也可写auto& x避免拷贝,性能更优)。
  4. 原地修改:将不等于val的元素依次写入数组前半部分,完成原地移除。
  5. 返回值k即为有效元素的数量,调用者可通过k截取结果。

四、原理解析:为什么返回 k 就够了?

很多同学会疑惑:函数只返回了 k,为什么评测机能拿到正确数组?

核心原因有两点:

  1. 原地修改nums是引用传递,函数内部已经把有效元素覆盖到了数组前k位。
  2. 约定返回值k告诉调用者「有效元素有多少个,都存在数组前半部分」,评测机会根据k截取前k个元素与预期结果对比。

以示例[3,2,2,3]为例:

  • 遍历后数组变为[2,2,3,3]k=2
  • 评测机截取前 2 个元素[2,2],与预期一致,判定通过。

五、复杂度分析

  • 时间复杂度:O (n),仅遍历一次数组,所有操作均为常数级。
  • 空间复杂度:O (1),仅使用常数级额外空间,原地修改无额外内存开销。

性能优化:范围 for vs 传统 for

  • 范围 for 代码更简洁,可读性更高,适合遍历容器场景。
  • 底层实现与传统 for 一致,性能无差异,编译器会优化为等价的索引遍历。
  • 若需避免元素拷贝,可使用for (auto& x : nums),效率更优。

六、拓展:首尾双指针优化(可选)

val出现次数很少时,可使用首尾双指针进一步减少赋值操作:

class Solution { public: int removeElement(vector<int>& nums, int val) { int left = 0, right = nums.size(); while (left < right) { if (nums[left] == val) { nums[left] = nums[right - 1]; right--; } else { left++; } } return left; } };
  • 思路:左指针找val,右指针找非val,交换两者,减少无效赋值。
  • 时间复杂度仍为 O (n),但赋值次数更少,适合val稀疏场景。

七、总结

  • 核心思想:双指针法实现原地移除,时间 / 空间复杂度最优。
  • 代码极简:范围 for 让代码更简洁易读,适合日常开发。
  • 关键理解:返回k是有效元素计数,数组已在函数内原地修改,两者配合完成题目要求。

这道题是数组操作的基础入门题,掌握双指针思想和范围 for 的使用,对后续学习更复杂的数组 / 链表操作有很大帮助。

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

相关文章:

  • 终极量化交易指南:用VectorBT快速实现Python策略回测
  • 手把手教你用Llama-3.2V-11B-cot:像聊天一样轻松实现图片智能分析
  • OpenClaw语音交互:ollama-QwQ-32B驱动本地智能家居控制
  • 备考小托福(TOEFL Junior)好用的背词软件
  • 告别Docker内置数据库:手把手教你用宝塔MySQL独立部署NocoBase(附完整配置流程)
  • CYBER-VISION零号协议在SolidWorks等工业设计软件中的集成展望
  • langchain和pytorch结合笔记
  • 磁滞回线实验避坑指南:从仪器校准到数据记录的5个关键细节
  • 全国标识标牌、交通设施、波形护栏厂家哪家好?2026年十大专业供应商推荐榜 - 深度智识库
  • BetterGI:基于计算机视觉的原神自动化辅助工具完全指南
  • 解锁UEFI启动画面定制:HackBGRT深度实践指南
  • 高效求职新范式:智能投递工具全平台应用指南
  • AI 创作者指南:10.AI 个人品牌打造:风格、定位与差异化
  • 2026年上海成都口碑好的海外留学机构推荐,专业留学服务企业全解析 - 工业品网
  • 设计师福音:自建Penpot私有云全记录(Docker版)从安装到团队权限管理实战
  • 终极Windows 11优化指南:一键清理系统垃圾,让电脑焕然一新
  • 幻境·流金开发者接口:Python调用API生成高清图的代码实例
  • ruoyi-vue-pro部署避坑指南:从JDK17到MySQL8的完整配置流程
  • AML启动器:智能管理XCOM 2模组的一站式解决方案
  • 5分钟极速配置OpenCore EFI:OpCore Simplify智能工具全面指南
  • 2026年江浙沪皖口碑好的危废处理公司推荐,能优化客户体验的企业全解析 - 工业品牌热点
  • 从倒立摆到无人机:雅可比矩阵线性化如何让‘不稳定’系统变得可控?
  • 如何快速修复Windows更新故障:3步使用重置工具完整指南
  • 社交媒体内容管理:用万物识别中文镜像自动标注图片标签
  • 3分钟学会本地Cookie导出:Get cookies.txt扩展完整教程
  • 别再只调PID了!用Simulink从电机传递函数到状态方程,手把手教你搭建完整仿真模型(附源码)
  • 400字节如何颠覆在线编辑?揭秘TinyEditor的技术魔法
  • STM32驱动TCS34725颜色传感器
  • 深度学习项目训练环境体验:基于专栏的实战环境,快速验证模型
  • gowebsocket架构解析:从零搭建高性能即时通讯平台