题目:给定一个链表,删除其中所有值重复的节点,只保留原始链表中没有重复值的节点。
注:这题不同于我们通常理解的去重操作,这题是要把重复的节点统统删除,一个不留!
例子:1->2->3->3->4->4->5,应该返回 1->2->5,值为3和4的节点一个不留!
思路:当我们发现前后两个节点的值不相等时,这证明前一个节点肯定不是要删除的节点,而后一个节点则不能保证,所以这时,我们要处理的链表规模就可以缩减到以第二个节点为起始的链表,同时让第一个链表和后面问题的返回值链接起来;如果发现前后两个节点的值相等时,那么就不断的递进指向第二个节点的指针,直到节点值不再相等,那么这两个指针包含的一个左闭右开区间就是我们要跳过的区间。
代码如下:
鲁棒:head为nullptr时程序不会崩溃,可以正确执行!
/**
* 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)
{
//头节点指向链表第一个节点
ListNode phead = ListNode(0);
phead.next = head;
//我们用这个指针指向当前不包括重复节点的链表的末尾
ListNode *ph = &phead;
//这两个指针用于确定重复节点的范围,也就是要跳过的节点范围
ListNode *s = nullptr, *e = nullptr;
//注意,我们必须在每次循环开始时更新s和e,这样当出现连续的几组重复节点时我们也可以正确删除
while((s = ph->next) && (e = s->next))
{
//前后两个节点值不相等,则更新ph
if(s->val != e->val)
ph = s;
//否则,跳过重复节点,同时更新ph->next
else
{
while(e && s->val == e->val) e = e->next;
ph->next = e;
}
}
return phead.next;
}
};
下面是运行结果: