力扣 leetcode 82. 删除排序链表中的重复元素 II
问题描述
给定一个已排序的链表的头 head
, 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
提示:
- 链表中节点数目在范围
[0, 300]
内 -100 <= Node.val <= 100
- 题目数据保证链表已经按升序 排列
示例
示例 1:
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
示例 2:
输入:head = [1,1,1,2,3]
输出:[2,3]
解题思路
本题要注意的是要把所有重复数字的节点都删除。例如,[1,1,1]
删除后是 []
,而不是 [1]
。我们可以使用双指针来实现删除操作,具体做法为:
此时pre->next->val != cur->val
,我们将 cur
和 pre
都指向下一个节点即可。 注意,我们在表头新增了一个节点,这样就能处理链表起始节点的值是重复的情况。
此时还是可以继续将 pre
和 cur
指针向后移。
此时, pre->next->val == cur->val,应该要将这两个节点删除。同时,我们还是要先找到 cur
所指向的下一个节点的位置。
我们将值为 3
的节点删除,并将 pre->next
指向后面第一个值不为 3
的节点。同时令 cur
指向 pre->next
的下一个节点。此时我们发现 pre->next->val == cur->val
,因此我们继续上面的步骤。
我们发现,cur
此时已经变成了 nullpr
,这说明我们已经遍历完链表了,并得到了最终结果。最终代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head == nullptr || head->next == nullptr){
return head;
}
ListNode* cur = new ListNode(200);
cur->next = head;
head = cur;
cur = head->next->next;
ListNode* pre = head;
ListNode* tmp = nullptr;
while(cur != nullptr){
if(pre->next->val == cur->val){ // 判断当前节点是否需要删除
tmp = cur->next;
while(tmp != nullptr){ // 寻找后面第一个值不为 pre->next->val 的节点
if(tmp->val == cur->val){ // 值相同时,将这些多余的节点删除
tmp = tmp->next;
delete cur->next;
cur->next = tmp;
}
else{ // 已经找到了
break;
}
}
delete cur;
cur = nullptr;
delete pre->next; //删除pre->next和cur这两个重复节点
pre->next = nullptr;
if(tmp == nullptr){ // 说明已经找到了末尾,可以直接返回最终结果了
return head->next;
}
else if(tmp->next == nullptr){ // 说明后面只有一个节点,也可以直接返回了
pre->next = tmp;
return head->next;
}
else{ // 后续还有很多节点,继续查找
pre->next = tmp;
cur = tmp->next;
}
}
else{ // 无重复值
pre = pre->next;
cur = cur->next;
}
}
return head->next;
}
};
可以看到,上述代码的关键就是保证 pre
和 cur
指针之间间隔一个元素。
本文来自博客园,作者:greatestchen},转载请注明原文链接:https://www.cnblogs.com/greatestchen/p/16941046.html