第11天 删除有序数组中的重复项 II

题意: 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入数组 并在使用 O(1) 额外空间的条件下完成。

题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/

视频链接:https://www.bilibili.com/video/BV18G5UzzE8c/

一、看到题目的第一想法

这道题是「有序数组去重,每个元素最多保留两次」,和经典的快慢指针去重题是同类型的变种题。

  1. 核心直觉:因为数组是有序的,重复元素一定是连续的,所以可以用快慢指针来实现「原地修改」,不需要额外空间。
  2. 快慢指针的角色定位
    • fast 指针负责遍历整个数组,寻找符合条件的元素(也就是不会让重复次数超过 2 次的元素)。
    • slow 指针负责维护「有效数组」的末尾位置,记录下一个可以存放新元素的位置。
  3. 边界条件预判:当数组长度 ≤ 2 时,不管元素是否重复,都可以直接返回原长度,因为最多也只有两个元素,天然满足 "不超过两次重复" 的要求。

二、实现过程中遇到的困难

  1. 慢指针起始位置的选择 一开始很容易沿用 "去重保留一次" 的写法,把 slow 初始化为 1。但这道题允许保留两次,前两个元素天然有效,所以 slow 应该从索引 2 开始,直接从第三个元素开始判断是否需要替换。
  2. 判断条件的误区 很容易错误地用 nums[slow-1]nums[fast] 比较,这样会误判 "连续三个相同元素" 的情况。正确的逻辑是:只要 fast 指向的元素,和 slow 维护的有效数组中倒数第二个元素不同,就说明它还没出现过三次,可以加入有效数组 。也就是 nums[slow-2] != nums[fast]
  3. 指针移动的顺序问题 一开始可能会把 ++fast 写在 if 分支里,导致循环中 fast 没有每次都移动,出现死循环或者漏遍历的情况。fast 指针必须在每次循环中都移动,只有满足条件时才移动 slow 指针。
  4. 对 "原地修改" 的理解偏差一开始可能会想着额外开一个数组存结果,忽略了题目要求的「原地修改」和「O (1) 额外空间」限制,而快慢指针刚好能满足这一点。

三、今日收获心得

  1. 快慢指针的通用模板思想 这类「有序数组去重 / 移除指定元素」的题目,快慢指针是通用解法:
    • fast 遍历原数组,筛选有效元素。
    • slow 维护有效数组的写入位置,原地覆盖修改。这道题只是把 "保留一次" 的逻辑改成了 "保留两次",核心框架没有变。
  2. 有序数组的隐藏优势有序数组的重复元素是连续的,这让我们不需要额外的哈希表统计次数,只需要通过和前面固定位置的元素比较,就能判断重复次数,大大优化了空间复杂度。
  3. 边界条件的重要性 一开始处理 numsSize <= 2 的情况,不仅能减少后续循环的无效执行,也避免了数组越界的问题,写算法题时先处理边界条件是个好习惯。
  4. 条件判断的本质理解 这道题的核心条件 nums[slow-2] != nums[fast],本质是在判断「当前元素是否已经在有效数组中出现了两次」,而不是简单的和前一个元素比较。理解了这一点,就可以轻松扩展到 "允许重复 k 次" 的通用场景(只需要把 slow-2 改成 slow-k 即可)。
相关推荐
无限进步_2 小时前
C++ 继承机制完全解析:从基础原理到菱形继承问题
java·开发语言·数据结构·c++·vscode·后端·算法
不知名的忻2 小时前
并查集(QuickUnion)
java·数据结构·算法·并查集
数智化精益手记局2 小时前
仓库安灯管理系统的异常响应机制:破解仓库安灯管理系统的跨部门协同难题
大数据·数据结构·人工智能·制造·精益工程
小张成长计划..3 小时前
【C++】25:哈希表的实现
数据结构·哈希算法·散列表
米啦啦.3 小时前
B-树,,
数据结构·b树·b-树
shy^-^cky3 小时前
文件的逻辑结构+ 物理结构
数据结构·操作系统·文件·数据·逻辑结构·物理结构·文件结构
睡觉就不困鸭3 小时前
第14天 四数之和
数据结构·算法
我不是懒洋洋3 小时前
手写一个线程安全的哈希表:从原理到实战
数据结构
云泽8083 小时前
二叉树高阶笔试算法题精讲(一):序列化、层序遍历、LCA 与 BST 转换
数据结构·c++·算法
嘻嘻哈哈樱桃4 小时前
牛客经典101题题解集--二叉树
java·数据结构·python·算法·leetcode·职场和发展