题目描述
一个有序数组,原地删掉重复的数,返回去重后的长度。
nums = [1, 1, 2, 2, 3]
输出 = 3 (前三个变成 1,2,3)
思路解析
i 往前走,挨个检查;j 指向下一个该放新数字的位置。发现新数字,就放到 j,然后 j 往前走一格。
准备:i = 0, j = 0:蓝色 i 是快指针,紫色 l 是慢指针 j,两个都从开头出发。
i = 0 · 第一个数:第一个数 1 肯定保留——它前面没数可以重复。
i = 0 · 放入:把 1 放到 j 位置(本来就在 0 号位),慢指针 j 前进到 1。
i = 1 · 看 1:当前 1 和它前一个 1 相同,重复了。跳过,j 不动,只让 i 继续走。
i = 2 · 看 2:当前 2 和前一个 1 不同,是新数字!该把它码到 j 位置了。
i = 2 · 放入:把 2 写到 1 号位(覆盖掉那个多余的 1),慢指针 j 前进到 2。看,前面已经是 [1, 2] 了。
i = 3 · 看 2:当前 2 和前一个 2 相同,重复,跳过。j 不动。
i = 4 · 看 3:当前 3 和前一个 2 不同,新数字!
i = 4 · 放入:把 3 写到 2 号位,慢指针 j 前进到 3。
结束:i 走完了。前 j = 3 个数 [1, 2, 3] 就是去重后的数组,返回长度 3。后面的数不用管。
快慢指针是数组题的万能套路:移除元素、移动零、删重复,都是 i 探路、j 安放。
参考代码(Python)
Python
1class Solution:
2 def removeDuplicates(self, nums):
3 j = 0 # 慢指针:放新数的位置
4 for i in range(len(nums)): # 快指针:逐个检查
5 if i == 0 or nums[i] != nums[i-1]: # 是新数?
6 nums[j] = nums[i] # 放到 j
7 j += 1 # j 前进
8 return j复杂度分析
- 时间复杂度:O(n) —— i 只走一遍
- 空间复杂度:O(1) —— 在原数组上改,不额外开空间
套路模板
移除元素、移动零、去重,都是把「该保留的」依次写到 j。
Python
1# 原地处理:i 探路,j 安放
2j = 0
3for i in range(len(nums)):
4 if 该保留(nums[i]):
5 nums[j] = nums[i]
6 j += 1
7return j # 前 j 个就是答案易错点
- ❌ if nums[i] != nums[i-1](i=0 越界) → ✅ if i==0 or nums[i] != nums[i-1](第一个数没有「前一个」)
- ❌ 返回 j-1 或 j+1 → ✅ 返回 j(j 每写一次就 +1,正好等于个数)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。