难度中等437
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
示例 1:
输入: 1->2->3->3->4->4->5 输出: 1->2->5示例 2:
输入: 1->1->1->2->3 输出: 2->3
1、标记法
非常清晰的题解方法,我用C++改写过来的。方法不是在原来链表上进行删除操作,那样太不省事了。
而是,利用不重复元素把节点重新链接到新链表上形成新链表。
我发现链表的好处就在于可以随时重组链表结点,对于删除和插入操作能很方便。这也是以后对链表算法题有一个基础的处理方式:
不一定非要在原来链表上操作,可以重新生成新的链表,尤其是针对删除重复这样的问题。
这题还是用到了标记方法。
/**
* 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) {
ListNode* dummy = new ListNode(0);
ListNode* prev = dummy;
while(head){
bool unique = true; //标记是否重复出现
ListNode* nextNode = head->next;
while(nextNode != nullptr && nextNode->val == head->val){
ListNode* tmp = nextNode->next;
delete nextNode;
nextNode = tmp;
unique = false;
}
if(unique){
prev->next = head;
prev = prev->next;
}else{
delete head;
}
head = nextNode;
}
prev->next = nullptr;
return dummy->next;
}
};
2、双指针法
双指针方法也是非常容易理解的!
/**
* 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) {
ListNode* prev = new ListNode(0);
prev->next = head;
head = prev;
ListNode *L, *R;
while(prev->next != nullptr){
L = prev->next;
R = prev->next;
while(R->next && R->next->val == L->val){ //判断是否有重复
R = R->next;
}
if(L == R){ //没有重复
prev = prev->next;
}else{ //有重复
prev->next = R->next;
while(L != R){ //及时释放
ListNode* tmp = L;
L = L->next;
delete tmp;
}
delete L;
}
}
return head->next;
}
};
有关防止内存泄漏问题,我有一个小问题:
为什么这样写就会报错内存泄漏呢???!!!