个人直观版解题思路:
通过快慢指针剔除重复节点,考虑到第一个节点可能存在重复,故要新建立一个头节点指向结果。
重复的节点存在的情况有两种:
- 偶数个重复(双指针跳跃剔除偶数个重复)
- 奇数个重复(repeat变量记录奇数个重复的情况,再排除)
具体意思是:
- 情况1比如: 2->3->3->4, 3重复了两次(偶数个重复),当slow->3,fast->3时
- 满足第一种情况,则slow=fast.next=4, fast=slow.next=null,便直接跳过两个重复节点
- 情况2比如: 2->3->3->3->4,3重复了三次(奇数个重复),必然会经过第一种情况。然后完成第一种情况后,快慢指针分别指向:slow->3,fast->4时,repeat=3,虽然slow.val!=fast.val,但仍然是重复的节点
- 满足第二种情况,则slow=fast=4, fast=fast.next=null,第二次跳过奇数个重复节点
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode deleteDuplication(ListNode pHead) {
if (pHead == null || pHead.next == null) { // 只有0个或1个结点,则返回
return pHead;
}
//新建头节点
ListNode res = new ListNode(0);
//快慢指针
ListNode slow = pHead, fast = pHead.next;
//结果
ListNode pre = res;
//记录重复的情况
int repeat = 0;
while(fast!=null){
//第一种情况:偶数个重复
if(slow.val==fast.val){
repeat = slow.val;
slow = fast.next;
//为了防止空指针异常
fast = slow==null? null:slow.next;
//第二种情况:奇数个重复
}else if(repeat==slow.val){
slow = fast;
fast = fast.next;
//无重复情况
}else{
res.next = slow;
fast = fast.next;
slow = slow.next;
res = res.next;
}
}
//最后的情况还要处理
if(slow!=null && repeat!=slow.val){
res.next = slow;
}else{
res.next = null;
}
return pre.next==null? null: pre.next;
}
}