【LeetCode】26. 删除有序数组中的重复项
解题思路
本题要求对非严格递增有序数组进行原地去重,核心在于双指针法的高效实现。通过快指针遍历数组,慢指针标记唯一元素的位置,既保证时间复杂度为 O(n),又满足空间复杂度 O(1) 的要求。以下是具体实现策略:
关键步骤
-
边界处理
若数组为空,直接返回 0;若数组长度为 1,直接保留该元素。 -
双指针初始化
slow指针标记唯一元素的插入位置(初始为 1,因为第一个元素无需处理)。fast指针遍历数组(从索引 1 开始)。
-
遍历与更新
当fast指针发现当前元素与前一个不同时,将其复制到slow指针位置,并移动slow指针。 -
终止条件
遍历完成后,slow的值即为去重后的数组长度。
func removeDuplicates(nums []int) int { n := len(nums) if n == 0 { return 0 } slow := 1 // 慢指针从第二个位置开始(第一个元素无需处理) for fast := 1; fast < n; fast++ { // 当发现新元素时,更新慢指针位置 if nums[fast] != nums[fast-1] { nums[slow] = nums[fast] slow++ } } return slow }
复杂度分析
| 指标 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 单次遍历数组 |
| 空间复杂度 | O(1) | 仅使用两个指针变量 |
运行示例
func main() { // 示例1 nums1 := []int{1, 1, 2} k1 := removeDuplicates(nums1) fmt.Println("示例1输出:", k1, nums1[:k1]) // 输出: 2 [1 2] // 示例2 nums2 := []int{0, 0, 1, 1, 1, 2, 2, 3, 3, 4} k2 := removeDuplicates(nums2) fmt.Println("示例2输出:", k2, nums2[:k2]) // 输出: 5 [0 1 2 3 4] }
核心逻辑解析
-
原地修改原理
Golang 的切片(Slice)底层是数组的引用,直接修改nums[slow]会同步修改原始数组。 -
非严格递增特性
由于数组已排序,重复元素必然连续出现,因此只需比较相邻元素即可判断是否重复。 -
去重动态过程
以输入[0,0,1,1,1,2]为例:fast=1:nums[1]=0与前一个相同,不操作。fast=2:nums[2]=1与前一个不同 →nums[1]=1,slow=2。fast=5:nums[5]=2与前一个不同 →nums[2]=2,slow=3。
最终去重后数组为[0,1,2],长度为 3。
扩展讨论
若题目允许最多保留两次重复元素(如 LeetCode 80),可扩展为:
- 增加计数器
count记录当前重复次数。 - 当
count ≤ 2时保留元素,否则跳过。

浙公网安备 33010602011771号