【LeetCode】80. 删除有序数组中的重复项 II
在有序数组中原地删除重复元素,使每个元素最多出现两次,可以通过双指针法高效实现。以下是详细实现方法及代码解析:
核心思路:快慢双指针法
-
指针定义:
- 快指针(fast):遍历数组,探测新元素位置
- 慢指针(slow):标记当前有效数组的末尾位置,确保前
slow个元素符合条件
-
关键逻辑:
- 有序数组中重复元素连续出现,因此只需比较当前元素与慢指针前两位的值
- 若
nums[fast] != nums[slow-2],说明当前元素未超过两次重复,需保留;否则跳过
-
边界处理:
- 数组长度 ≤ 2 时无需处理,直接返回原长度
Go 代码实现
func removeDuplicates(nums []int) int { if len(nums) <= 2 { return len(nums) } slow := 2 for fast := 2; fast < len(nums); fast++ { if nums[fast] != nums[slow-2] { nums[slow] = nums[fast] slow++ } } return slow }
代码解析
-
初始化:
slow从索引 2 开始,因为前两个元素无论是否重复均可保留
-
循环遍历:
- 快指针
fast从 2 开始遍历数组 - 若
nums[fast]与nums[slow-2]不同,说明当前元素未达到两次重复上限,将其赋值到nums[slow]并移动慢指针
- 快指针
-
时间复杂度:
- O(n),仅需一次遍历数组
-
空间复杂度:
- O(1),未使用额外存储空间
示例验证
- 输入:
nums = [1,1,1,2,2,3] - 处理过程:
slow初始为 2,fast从 2 开始fast=2:nums[2]=1与nums[0]=1相同 → 跳过fast=3:nums[3]=2与nums[1]=1不同 → 赋值到slow=2,此时数组前 3 项为[1,1,2]- 最终
slow=5,数组前 5 项为[1,1,2,2,3],长度返回 5
对比其他方法
| 方法 | 优势 | 适用场景 |
|---|---|---|
| 双指针法 | 时间复杂度 O(n) | 有序数组去重 |
| 暴力遍历法 | 逻辑简单 | 小规模无序数组 |
| 哈希表法 | 支持无序数组去重 | 需要保留任意次数元素 |
扩展:允许最多 k 次重复的通用解法
通过参数化允许的最大重复次数 k,可扩展为通用函数:
func removeKDuplicates(nums []int, k int) int { if len(nums) <= k { return len(nums) } slow := k for fast := k; fast < len(nums); fast++ { if nums[fast] != nums[slow-k] { nums[slow] = nums[fast] slow++ } } return slow }
将 k=2 调用即可适配本题需求。
总结
双指针法是解决有序数组去重问题的经典方案,通过合理控制比较逻辑和指针移动规则,既能保证高效性,又满足原地修改的约束条件。此方法在 LeetCode 等算法题中广泛应用,建议深入理解其核心思想以应对类似问题。

浙公网安备 33010602011771号