编程训练:
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
示例:
- 输入: 1->2->3->3->4->4->5
输出: 1->2->5 - 输入: 1->1->1->2->3
输出: 2->3
解法:
1.双指针
时间复杂度O(N)
空间复杂度O(1)
/**
* 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 *h = new ListNode(0);
h->next = head;
ListNode *pre = h;
ListNode *cur = pre->next;
while (cur != nullptr)
{
int cntNumber = 0;
ListNode *move = cur;
while (move != nullptr && move->val == cur->val)
{
move = move->next;
cntNumber++;
}
if (cntNumber > 1)
pre->next = move;
else
pre = cur;
cur = move;
}
return h->next;
}
};
也可以创建一个新链表res, 一个用于指向尾结点指针rear和用于添加新元素的指针temp。然后我们需要一个flag来检测是否是duplicate。如果不是duplicate,就将head指向的结点添加进新链表中,并更新rear和head。如果是,则将head更新,注意此时rear也要同时更新。因为出现当前head结点已经是尾结点了,则可以将rear的next置空,结束循环,或者当前结点与上一结点的值不同,rear指向这个结点,防止rear的next指针仍然指向重复的元素。
时间复杂度O(N)
空间复杂度O(1)
/**
* 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 *temp;
ListNode *res = new ListNode();
ListNode *rear = res;
bool flag;
while (head)
{
flag = false;
while (head->next && head->val == head->next->val)
{
head= head->next;
flag = true;
}
if (!flag)
{
temp = head;
rear->next = temp;
rear = temp;
head = head->next;
}
else
{
head = head->next;
rear->next = head;
}
}
return res->next;
}
};