这个删除重复不太常规的是:它不是删除多出来的剩下一个,而是比如有三个1,1重复了,那这三个1节点都不要
ListNode* deleteDuplicates(ListNode* head) {
if (!head) return head;// 空链表直接返回
// 虚拟头指针避免空头问题
ListNode* virtual_node = new ListNode();
virtual_node->next = head;
// 指针1用来遍历,指针2用来标记重复段的起点
// 还需要一个指针标记重复段的前一个位置
ListNode* ptr1 = head->next, *ptr2 = head,*ptr3 = virtual_node;
while (ptr1){
if (ptr1->val != ptr2->val) {
if (ptr2->next->val!=ptr1->val)
// 说明中间存在重复段了
ptr3->next = ptr1;
else ptr3 = ptr2;
ptr2 = ptr1;
}
ptr1 = ptr1->next;
}
// 还有一种情况是遍历指针走完了,但是最后一段还是重复段没有处理
if (ptr2->next) ptr3->next = nullptr;
return virtual_node->next;
}
三指针,ptr1用来遍历整个链表,ptr2用来标记重复段的起始位置,ptr3用来标记重复段的前一个位置
删除重复段的操作就是:将ptr3的next指针指向ptr1
另外需要注意的是两个情况:
- 原本的头节点被删除了,考虑空头的情况用虚拟头节点技巧处理
- 链表的最后一段是重复的,但是遍历指针ptr1跑完了,循环体不再处理,这时候就需要一个收尾处理,ptr1最后的位置应该是指向结果链表的最后一个元素