82. 删除排序链表中的重复元素 II
是一个有序链表
错误代码
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode dummy = new ListNode();
dummy.next = head;
while(head != null && head.next != null) {
if (head.val == head.next.val) {
head.next = head.next.next;
}
head = head.next;
}
return dummy.next;
}
}
这段代码的目的是删除单链表中的所有重复元素,但是它只能删除连续且相邻的重复元素,并且存在一个逻辑错误。错误在于当发现重复元素时,代码没有保持当前节点不变以继续检查后续是否还有重复元素,而是直接移动到了下一个节点。这会导致在一系列连续重复元素中,只删除了第一个重复元素后的一个元素,而不是删除所有重复的元素。
例如,对于链表 1 -> 2 -> 2 -> 3
,按照这段代码的逻辑,处理后的链表将会是 1 -> 2 -> 3
,这是正确的。但是,对于链表 1 -> 2 -> 2 -> 2 -> 3
,处理后的链表将会是 1 -> 2 -> 2 -> 3
,这是不正确的,因为它没有删除所有的重复元素。
为了修正这个问题,我们需要在发现重复元素时,不移动 head
指针,直到确保没有更多的重复元素。以下是修正后的代码:
public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if (head == null) return null;
ListNode dummy = new ListNode(0, head);
ListNode cur = dummy;
while (cur.next != null && cur.next.next != null) {
if (cur.next.val == cur.next.next.val) {
int dupVal = cur.next.val;
while (cur.next != null && cur.next.val == dupVal) {
cur.next = cur.next.next; // 删除重复元素
}
} else {
cur = cur.next; // 没有重复,移动到下一个节点
}
}
return dummy.next;
}
}
修正后的代码逻辑:
- 创建一个哑节点
dummy
,其next
指向head
,以简化边界条件处理。 - 使用
cur
指针遍历链表,初始时指向dummy
。 - 当
cur
的下一个节点和下下一个节点不为空时,检查这两个节点的值是否相等。- 如果相等,说明有重复元素。记录重复的值
dupVal
,然后使用一个循环删除所有值为dupVal
的节点。 - 如果不相等,说明当前节点不重复,
cur
指针移动到下一个节点。
- 如果相等,说明有重复元素。记录重复的值
- 返回
dummy.next
,即新链表的头节点。