Question
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.


本题难度Medium。

【复杂度】
时间 O(N) 空间 O(1)

【思路】
我在开始想出两个办法:

  • 遇到重复的就删除
  • 对重复的部分考察完毕后再整体删除

方法1有个麻烦:第一个重复数最后要另外删除。所以我使用方法2,为了便于理解我利用三个指针​​prev、fst、cur​​​(两个指针也可可以​​fst=prev.next​​​),​​prev​​​指向上一个不同的数的node,​​fst​​​指向本次重复数的第一个node,​​cur​​指向现在考察的node。例如:

..->1  ->2  ->2  ->2->3->..
| | |
prev fst cur
  • 如果​​cur.val==fst.val​​,cur向后移动一位
  • 如果​​cur.val!=fst.val​​(这个就是关键了):
如果 fst.next!=cur 说明该数有重复,就进行整体删除
否则,说明该数没有重复,就将`prev、fst、cur`都向前移动一位。

【附】
使用了fake是为了对只有一个node的情况进行处理

【注意】

  1. 这个方法对​​head=null​​的情况不能处理,所以有12-13行的处理
  2. 29-30行是为了对例如:​​1->1​​这种情况进行处理。
  3. 返回是 ​​return fake.next;​

【代码】

/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode deleteDuplicates(ListNode head) {
//require
if(head==null)
return head;
ListNode fake=new ListNode(-1);
fake.next=head;head=fake;
//invariant
ListNode prev=head,fst=prev.next,cur=fst;
while(cur!=null){
if(cur.val!=fst.val){
if(fst.next!=cur)
prev.next=cur;
else
prev=fst;
fst=cur;
}
cur=cur.next;
}
//in case: 1->1
if(fst.next!=cur)
prev.next=cur;
//ensure
return fake.next;
}
}

也可以写成双指针,因为​​fst=prev.next​​:

public class Solution {
public ListNode deleteDuplicates(ListNode head) {
//require
if(head==null)
return head;
ListNode fake=new ListNode(-1);
fake.next=head;head=fake;
//invariant
ListNode prev=head,cur=prev.next;
while(cur!=null){
if(cur.val!=prev.next.val){
if(prev.next.next!=cur)
prev.next=cur;
else
prev=prev.next;
}
cur=cur.next;
}
if(prev.next.next!=cur)
prev.next=cur;
//ensure
return fake.next;
}
}