HoRain云--高效双指针法:删除有序数组重复项

🎬 HoRain云小助手:个人主页
🔥 个人专栏: 《Linux 系列教程》《c语言教程》
⛺️生活的理想,就是为了理想的生活!
⛳️ 推荐
前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。
专栏介绍
| 专栏名称 | 专栏介绍 |
| 本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。 | |
| 本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制! | |
| 全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。 | |
| 本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。 | |
| 本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。 | |
| 本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等) |
目录

删除有序数组中的重复项是一个常见的算法问题,其核心在于原地修改数组并使用 O(1) 额外空间。由于数组是有序的,重复元素会连续出现,这为高效解决问题提供了条件。
以下是解决该问题的几种Python方法,我将为你详细解释其中最优雅和高效的双指针法,并提供代码示例。
🔍 方法一:双指针(快慢指针)
这是解决此类问题的最常见且高效的方法。
思路
-
初始化指针:设置一个慢指针
slow,其初始位置为0(或1,取决于实现),用于指向下一个唯一元素应存放的位置;一个快指针fast,用于遍历数组。 -
遍历数组:快指针
fast从头到尾遍历数组。 -
发现不重复元素:当
nums[fast]不等于nums[slow](或nums[slow-1],取决于slow的初始位置)时,说明遇到了新的唯一元素。将slow指针后移一位,并将nums[fast]的值赋给nums[slow]。 -
返回长度:遍历结束后,
slow指针的位置(或slow+1)即为新数组的长度。
代码实现
def removeDuplicates(nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums: # 处理空数组的情况
return 0
slow = 1 # 慢指针,从索引1开始(因为索引0的元素肯定是唯一的)
n = len(nums)
for fast in range(1, n): # 快指针从索引1开始遍历
if nums[fast] != nums[fast - 1]: # 当前元素与前一个元素比较
nums[slow] = nums[fast] # 将新的唯一元素赋值给slow指针的位置
slow += 1 # 慢指针后移
return slow # 返回新数组的长度
# 示例用法
nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
length = removeDuplicates(nums)
print(f"新数组长度: {length}")
print(f"修改后的数组前{length}个元素: {nums[:length]}")
# 输出:
# 新数组长度: 5
# 修改后的数组前5个元素: [0, 1, 2, 3, 4]
另一种常见的双指针写法,slow从0开始:
def removeDuplicates(nums):
if not nums:
return 0
j = 0 # 慢指针
for i in range(1, len(nums)): # i 是快指针
if nums[i] != nums[j]:
j += 1
nums[j] = nums[i]
return j + 1
复杂度分析
-
时间复杂度:O(n),其中 n 是数组的长度。快指针
fast只需遍历数组一次。 -
空间复杂度:O(1)。我们只使用了常数个额外变量(
slow和fast或i和j)。
⚠️ 其他方法及注意事项
-
使用
pop方法:某些方法在遍历过程中遇到重复元素时使用pop来移除。一般不推荐,因为pop操作的时间复杂度为 O(n),导致总体时间复杂度升至 O(n²),尤其在数组较大时效率较低。 -
使用
count方法:在循环中使用nums.count(nums[i])判断重复并删除。极其不推荐,count方法本身是 O(n) 操作,会使算法的时间复杂度变得非常高(例如 O(n²) 或更糟)。 -
哈希集合去重:虽然
set可用于去重,但无法满足“原地修改”和“O(1)空间”的要求,因为它需要额外空间存储集合。
💎 总结
对于删除有序数组中的重复项问题,双指针法是最优解。它高效地利用了数组已排序的特性,通过一次遍历和原地交换,以 O(n) 的时间复杂度和 O(1) 的空间复杂度完成任务。
| 方法 | 时间复杂度 | 空间复杂度 | 推荐度 |
|---|---|---|---|
| 双指针 | O(n) | O(1) | ★★★★★ |
| 使用 | O(n²) | O(1) | ★☆☆☆☆ |
| 使用 | O(n²) (或更糟) | O(1) | ☆☆☆☆☆ |
希望这些解释和代码示例能帮助你更好地理解如何解决这个问题。如果你有兴趣,可以尝试一下LeetCode的类似题目(如第80题,允许元素最多出现两次)来巩固这个技巧。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
更多推荐

所有评论(0)