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

LeetCode 80 · 删除有序数组中的重复项 II:通用模板的威力

LeetCode 26 要求每个元素最多出现一次这道题放宽到最多出现两次。看起来只是把1改成了2但这个小改动背后藏着一个通用的快慢指针模板——把2换成任意整数m代码几乎不用动。这就是模板的威力改一个数字通吃一整类题。题目长什么样给你一个有序数组nums请你原地删除重复出现的元素使得出现次数超过两次的元素只出现两次返回删除后数组的新长度。输入nums [0,0,1,1,1,1,2,3,3]输出7, nums [0,0,1,1,2,3,3]说人话就是数组已经排好序了每个元素最多保留两个多余的删掉。和 LeetCode 26 唯一的区别就是最多保留几个——26 题是 1 个这道题是 2 个。从 LeetCode 26 说起改一个数字就行先回顾一下 LeetCode 26 的代码# LeetCode 26最多保留 1 个defremoveDuplicates(self,nums):ifnotnums:return0k1# 前 1 个直接保留foriinrange(1,len(nums)):# 从第 1 个开始扫ifnums[i]!nums[k-1]:# 和倒数第 1 个已保留元素比nums[k]nums[i]k1returnk现在要改成最多保留 2 个只需要做三处修改# LeetCode 80最多保留 2 个defremoveDuplicates(self,nums):iflen(nums)2:returnlen(nums)k2# 前 2 个直接保留foriinrange(2,len(nums)):# 从第 2 个开始扫ifnums[i]!nums[k-2]:# 和倒数第 2 个已保留元素比nums[k]nums[i]k1returnk改动点就三个1→21→2k-1→k-2。逻辑完全一样。为什么nums[k-2]就够了这是这道题最精妙的地方。很多第一反应是我需要计数器记录当前元素出现了几次——不需要。关键推理因为数组是有序的相同元素一定相邻。 nums[k-2] 是已保留区域的倒数第二个位置。 如果 nums[i] ! nums[k-2] 说明 nums[i] 是个新元素或者虽然出现过但不超过两次 可以安全保留。 如果 nums[i] nums[k-2] 说明 nums[i] 至少是第三次出现了因为前面已经有 nums[k-2] 和它之间的那个 必须跳过。画个图更清楚已保留区域: [..., x, x, ...] ← nums[k-2] 和 nums[k-1] 可能都是 x ↑ nums[k-2] 当前扫描到 nums[i] x → x nums[k-2]说明前面已经有两个 x 了这是第三个 → 跳过 当前扫描到 nums[i] y (y ≠ x) → y ≠ nums[k-2]说明 y 出现不超过两次 → 保留不需要计数器不需要额外状态一个比较就够了。跑一遍示例示例 1nums [1,1,1,2,2,3]前两个直接保留: [1, 1, _, _, _, _], k 2 i2: nums[2]1, nums[k-2]nums[0]1 → 11, 第三次出现, 跳过 i3: nums[3]2, nums[k-2]nums[0]1 → 2≠1, 保留! nums[2]2, k3 i4: nums[4]2, nums[k-2]nums[1]1 → 2≠1, 保留! nums[3]2, k4 i5: nums[5]3, nums[k-2]nums[2]2 → 3≠2, 保留! nums[4]3, k5 结果: [1, 1, 2, 2, 3, _], k 5示例 2nums [0,0,1,1,1,1,2,3,3]前两个直接保留: [0, 0, _, _, _, _, _, _, _], k 2 i2: nums[2]1, nums[0]0 → 1≠0, 保留! nums[2]1, k3 i3: nums[3]1, nums[1]0 → 1≠0, 保留! nums[3]1, k4 i4: nums[4]1, nums[2]1 → 11, 第三次出现, 跳过 i5: nums[5]1, nums[2]1 → 11, 第四次出现, 跳过 i6: nums[6]2, nums[2]1 → 2≠1, 保留! nums[4]2, k5 i7: nums[7]3, nums[3]1 → 3≠1, 保留! nums[5]3, k6 i8: nums[8]3, nums[4]2 → 3≠2, 保留! nums[6]3, k7 结果: [0, 0, 1, 1, 2, 3, 3, _, _], k 7通用模板允许保留 m 个把2抽象成参数m就得到了一个通用模板defremoveDuplicates(self,nums:List[int],m:int2)-int:iflen(nums)m:returnlen(nums)kmforiinrange(m,len(nums)):ifnums[i]!nums[k-m]:nums[k]nums[i]k1returnkm的值对应题目m 1LeetCode 26每个元素最多出现 1 次m 2LeetCode 80每个元素最多出现 2 次m 3如果有 LeetCode 80 变体要求最多 3 次m 任意同一套代码改参数即可三道题放在一起看题目保留条件起始 k遍历起点比较LeetCode 27nums[i] ! val00和目标值比LeetCode 26nums[i] ! nums[k-1]11和前 1 个比LeetCode 80nums[i] ! nums[k-2]22和前 2 个比LeetCode 27 是过滤模式和固定值比26 和 80 是去重模式和已保留区域的元素比。去重模式的规律就是允许保留几个就和倒数第几个比。这道题教会我什么抨模板比抻代码更有价值如果你把 LeetCode 26 的代码背下来碰到 LeetCode 80 可能会懵——但如果你理解了和倒数第 m 个比这个模式改一个数字就过了。面试时也是一样面试官不会考你原题但会考你能不能把已知的模式迁移到新场景。不需要计数器第一反应往往是记录当前元素出现了几次但其实有序数组的特性让问题变得简单——只要和nums[k-m]比一下就知道是第几次出现了。这种用位置关系代替显式计数的技巧在数组和链表题里非常常见。边界条件len(nums) 2LeetCode 26 的边界是空数组if not numsLeetCode 80 的边界是长度不足 2if len(nums) 2。通用模板的边界是if len(nums) m。模板越通用边界条件越要小心。完整测试代码fromtypingimportListclassSolution:defremoveDuplicates(self,nums:List[int])-int:iflen(nums)2:returnlen(nums)k2foriinrange(2,len(nums)):ifnums[i]!nums[k-2]:nums[k]nums[i]k1returnkif__name____main__:sSolution()nums[1,1,1,2,2,3]ks.removeDuplicates(nums)print(fk{k}, nums{nums[:k]})nums[0,0,1,1,1,1,2,3,3]ks.removeDuplicates(nums)print(fk{k}, nums{nums[:k]})nums[1,1,1,1,1]ks.removeDuplicates(nums)print(fk{k}, nums{nums[:k]})nums[1,2,3,4,5]ks.removeDuplicates(nums)print(fk{k}, nums{nums[:k]})nums[1,1]ks.removeDuplicates(nums)print(fk{k}, nums{nums[:k]})nums[1]ks.removeDuplicates(nums)print(fk{k}, nums{nums[:k]})相关题目推荐LeetCode 26 · 删除有序数组中的重复项m1的特例LeetCode 27 · 移除元素过滤模式和固定值比较LeetCode 283 · 移动零同一个快慢指针模板
http://www.gsyq.cn/news/1380160.html

相关文章:

  • HybridCLR-Unity原生C#热更新终极方案
  • 终极城通网盘解析指南:3分钟获取高速直连下载地址的完整教程
  • 开源HR系统OpenHRMS:如何用模块化设计破解企业人事管理难题?
  • 财务怎么做经营分析?一文说清经营分析的9大体系30个指标!
  • 百联 OK 卡安全高效变现指南 - 购物卡回收找京尔回收
  • 数据挖掘是什么?数据分析、数据挖掘、数据统计三者的区别是什么
  • Skeptical Learning:人机协作式数据清洗框架的原理、实践与挑战
  • Obsidian PDF++解决方案:构建原生双向链接的知识管理生态系统
  • Taotoken 的用量看板与成本管理功能如何帮助团队控制 AI 支出
  • 【分享】AIDE Pro 制作属于自己的手机软件
  • XUnity自动翻译工具:如何让外语游戏瞬间变成你的母语版本?
  • 【稀缺首发】PlayAI首次开放评测接口权限!但我们已逆向解析其质量打分逻辑,并构建第三方可信验证框架
  • NLP —— Transformers库使用
  • taotoken模型广场功能详解与模型选型决策指南
  • 2026年厂区节能减排公司有哪些?工业能源托管与余热回收系统厂家实力推荐 - 品牌2025
  • 告别英文界面:Cobalt Strike 4.8 保姆级汉化安装与首次连接指南
  • WPF中Style和ControlTemplate的触发器有什么不同
  • 企业内统一AI开发环境借助Taotoken CLI实现快速配置
  • 项目文档:基于51单片机的篮球计分器设计
  • 用Icarus Verilog破解数字电路调试困局的实战心法
  • request接口调用的三种方法(1)
  • qobuz-dl 终极指南:如何轻松下载无损音乐建立个人高品质音乐库
  • sd卡分区了数据还能恢复吗,只需3种方法和视频教学,数据就能神奇地回来!
  • AI 分析重构(AI-Assisted Refactoring)详解
  • 济南黄金回收怎么选?福运来人气与口碑双冠 - 黄金回收
  • 音乐格式转换终极指南:3步解锁所有加密音频
  • 原神自动化助手GIS:3大核心功能彻底解放你的双手
  • 如何快速解锁加密音乐文件:3个简单步骤让音乐自由播放
  • ncmdumpGUI终极指南:3分钟搞定网易云音乐NCM文件转换
  • 2026最新实测快消品行业GEO优化公司哪家好?靠谱服务商与平台推荐 - 博客万