LeetCode 83. 删除排序链表中的重复元素
题目描述


题意分析
给定一个按升序排列的链表,删除其中多余的重复节点,使每个不同的值只保留一个节点,并返回处理后的头节点。某个值出现多次时,仍然要保留它的一份,而不是删除这个值对应的整组节点。
链表已经有序,因此相同值一定连续出现。只要处理好每一段连续重复节点,就完成了整条链表的去重;空链表应直接返回空。
解法:单指针跳过连续重复节点
核心思路
[!blue]
用指针
cur指向当前这组值准备保留的节点。它之前的部分已经完成去重,接下来只需要比较cur和它的后继:由于相同值连续出现,后继足以判断当前重复段是否已经结束。若两者值相同,保留
cur,执行cur.next = cur.next.next,让当前节点直接连向后继的后继。这是在链表连接中跳过一个多余节点,不需要复制节点或改变节点值。此时cur必须留在原地,因为新后继仍可能与它重复。若两者值不同,当前值的重复段已经清理完成。由于链表升序,后面的节点不可能再次出现当前这个值,所以可以放心令
cur = cur.next,处理下一组。每轮都会删除一个后继或把指针向后推进,未处理部分持续缩短。到达尾节点或空链表时结束。每组都保留第一个节点,所以原头节点不会被删除,也就不需要额外的哨兵节点;最终返回原来的
head。
解题步骤
- 令
cur = head,空链表会直接跳过循环。- 当
cur和cur.next都存在时,比较两者的值。- 值相同:执行
cur.next = cur.next.next,继续检查当前cur。- 值不同:把
cur前移一位。- 扫描结束后返回
head,保留从头开始的整条结果链表。
代码实现
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode cur = head;
while (cur != null && cur.next != null) {
if (cur.val == cur.next.val) {
// 删除后当前代表节点不动,新后继仍可能是重复值。
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
return head;
}
}
func deleteDuplicates(head *ListNode) *ListNode {
cur := head
for cur != nil && cur.Next != nil {
if cur.Val == cur.Next.Val {
// 删除后当前代表节点不动,新后继仍可能是重复值。
cur.Next = cur.Next.Next
} else {
cur = cur.Next
}
}
return head
}
复杂度分析
- 时间复杂度:$O(n)$,其中
n为节点数。每次比较都会删除当前后继或前进到该后继,每个原节点最多作为后继处理一次。- 空间复杂度:$O(1)$,只维护一个扫描指针,原地修改节点连接。
关键点总结
[!green]
- 利用「有序 ⇒ 重复相邻」,把全局去重变成局部比较。
- 删除重复节点后不能前进,否则会漏掉三个及以上的连续重复值。
- 本题保留每组第一个节点,原头节点始终有效;删除整组重复值是另一种要求,不能混用处理逻辑。
易错点总结
[!yellow]
- 删除重复后继后仍然推进
cur,会跳过对新后继的检查,连续多个重复节点可能没有清理干净。- 访问
cur.next前必须先判断cur非空;访问后继的值和指针前,还要确保后继存在。- 返回扫描指针
cur会丢掉前面已去重的节点,应返回一直保留的head。- 相邻值不同时才能推进指针;不能发现重复后把当前代表节点也删除,否则会把该值的全部节点删掉。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 82. 删除排序链表中的重复元素 II | 中等 | 同样识别有序重复段,原题删除该值的全部节点,本题保留一个代表。 |
| 26. 删除有序数组中的重复项 | 简单 | 同样利用相邻相等识别重复,数组用写指针覆盖,链表直接跳过节点。 |
| 19. 删除链表的倒数第 N 个结点 | 中等 | 用哨兵与前驱节点统一链表删改边界;本题每段重复值只保留一个,该题先用指针间隔定位倒数节点。 |
| 203. 移除链表元素 | 简单 | 用哨兵与前驱节点统一链表删改边界;本题每段重复值只保留一个,该题过滤所有目标值节点。 |
| 补充题 111. 提取有序链表中的重复值 | 中等 | 都利用有序链表中等值节点连续的性质逐段扫描;本题每段留一个,补充题只留下重复段。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!