题目:
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
.
这道题不同之处在于,要把重复的所有节点删除。要稍微复杂点。
思路:链表排序说明重复节点都处于相邻位置,遍历链表并比较当前节点是否和下一个节点重复.如果重复:删除下一个节点,重复该操作直到下一个节点为空或者和当前节点不重复,只要执行过删除操作,就说明原链表曾经有和当前节点重复的节点,根据题目要求,此时还需要将当前节点删除掉,所以在判断下一个节点为空或者和当前节点值不同时,将当前节点删除。如果不同:则移动到链表的下一个节点继续重复以上判断,直到链表结束。
Attention: 判断是否删除当前重复节点的条件很重要!如果删除掉一个重复节点后,之后的节点和当前节点一致,则保留当前节点,进行下次判断;否则删除当前节点;(当前节点是最后一个节点时也要删除) !!!!解决了重复节点奇偶数的问题(奇数保留当前节点,偶数删除当前节点)。
AC Code:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *deleteDuplicates(ListNode *head) {
//除排序链表中所有重复的节点,删除完成后,原链表中的重复节点全部删除。
//链表排序说明重复节点都处于相邻位置,遍历链表并比较当前节点是否和下一个节点重复
//如果重复:删除下一个节点,重复该操作直到下一个节点为空或者和当前节点不重复,只要执行过删除操作,就说明原链表曾经有和当前节点重复的节点,根据题目要求,此时还需要将当前节点删除掉,所以在判断下一个节点为空或者和当前节点值不同时,将当前节点删除。
//如果不同:则移动到链表的下一个节点继续重复以上判断,直到链表结束。
//Attention: 如果删除掉一个重复节点后,之后的节点和当前节点一致,则保留当前节点,进行下次判断;否则删除当前节点;(当前节点是最后一个节点时也要删除) !!!!解决了重复节点奇偶数的问题(奇数保留当前节点,偶数删除当前节点)。
if(head == NULL || head->next == NULL)
return head;
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* p, *q ,*pre;
p = head;
pre = dummyhead;
while( p != NULL)
{
//存在当前节点的下一个节点时
if(p->next != NULL && p->val == p->next->val)
{
//删除下一个重复节点
q = p->next;
p->next = q->next;
delete q;
//符合条件删除当前节点,否则保留 !!!!此处删除当前节点的判断条件很重要
if(p->next == NULL || (p->next != NULL && p->val != p->next->val))
{
// pre = p->next;
pre->next = p->next; //pre->next始终指向下一个要判断的节点 如1 1' 2 3 删除1'后,令pre指向2,再删除1,之后p重置为指向2
delete p;
p = pre->next; //重置p为下一个节点 pre起到一个游标尺的作用,始终卡在下一个节点,用于重置p。
}
}
else
{
//移动pre和p节点
pre = pre->next; //此处移动pre,不会影响dummyhead. 令pre指向新的地址。
p = p->next;
}
}
head = dummyhead->next; //dummyhead->next始终指向新链表的头结点(dummyhead是虚拟头结点)
delete dummyhead;
return head;
}
};