题目
给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回已排序的链表 。
示例 1:
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
示例 2:
输入:head = [1,1,1,2,3]
输出:[2,3]
提示:
链表中节点数目在范围 [0, 300] 内
-100 <= Node.val <= 100
题目数据保证链表已经按升序排列
思路
上一题:重复节点只保留一个,向后多看一个节点。
本题:重复节点一个都不留,向后多看多个节点。
- 当前情况不能用prev和cur来判断重复节点,此时prev引用一定指向不重复的节点,需要再引入一个next引用。(向后多走几步)
- 当链表中只有一个节点(next == null),不可能出现重复元素。
- 当cur.val != next.val时,说明cur不是重复节点,三个引用都向后移动一个单位。
- 当cur.val == next.val时,让next继续向后走,直到next指向与cur.val不相等的节点。此时prev到next之间全是需要删除的元素:prev.next = next; 当且仅当cur.val != next.val才能移动prev指针!此时cur指向next,next指向cur.next。
上面3种情况分别对应下面3副图:
代码
/**
* Definition for singly-linked list.
* 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) {
ListNode dummyHead = new ListNode(101);
dummyHead.next = head;
ListNode prev = dummyHead;
ListNode cur = prev.next;
while(cur != null) {
ListNode next = cur.next;
if(next == null) {
//此时链表中只有一个元素,不可能出现重复元素
return dummyHead.next;
} else if(cur.val != next.val) {
//此时cur不是重复节点,三个指针都向后移动一个单位
prev = prev.next;
cur = cur.next;
} else {
//此时cur.val == next.val,让next指针一直向后移动,直到与cur.val不相等的节点位置为止
while(next != null && cur.val == next.val) {
next = next.next;
}
//此时next指向了第一个不重复的元素,prev到next之间所有元素全部删除
prev.next = next;
cur = next;
}
}
return dummyHead.next;
}
}