删除有序链表中重复的元素
删除有序链表中重复的元素-I
这道题很简单,定义一个pre指针指向前,cur指向往后走,找到一个值不和pre相同的才停止,链接pre和cur,然后pre =cur,往后遍历即可。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* deleteDuplicates(ListNode* head) {
// write code here
if(head == nullptr || head->next == nullptr)
return head;
ListNode* pre = head;
ListNode* cur = pre;
while(cur)
{
cur = cur->next;
while(cur && cur->val == pre->val)
{
cur = cur->next;
}
pre->next = cur;
pre = cur;
}
return head;
}
};
删除有序链表中重复的元素-II
这道题的解题思路如下:首先从测试用例可以看出,重复的数字出现在链表头的时候我们是需要将链表头更改的,所以我们可以用一个哨兵位的头节点指向头。
其次难点在于:当出现下图的场景的时候,我们不能说next就一定是新的头部,我们这个时候应该要保持头head,然后下次cur指向next,next指向下一个位置,直到cur一开始就和next不相等(即类似cur为1,next为2的场景),才能说明cur是出现了一次,这个时候才能更新头部。
一个例子:
class Solution {
public:
/**
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* _deleteDuplicates(ListNode* head, ListNode* start)
{
if (head == nullptr || head->next == nullptr)
return head;
ListNode* cur = start;
ListNode* next = cur->next;
while (next && next->val == cur->val)
{
next = next->next;
}
//这里有特殊情况,若刚好cur为第一次出现并且next为空的情况,cur也是第一次出现。
if (next == cur->next) {
//这里说明cur一定是出现一次的,cur就是新的头,next就是下次cur遍历的位置
head->next = cur;
start = next;
}
else if (next == nullptr)
{
head->next = next;
return head;
}
else {
//这里表示头不变,并且下次cur需要从next位置出发,所以设置start
cur = head;
start = next;
}
return _deleteDuplicates(cur, start);
}
ListNode* deleteDuplicates(ListNode* head) {
// write code here
//会跟换头
ListNode* dummy = new ListNode(-1);
dummy->next = head;
_deleteDuplicates(dummy, dummy->next);
return dummy->next;
}
};
鸠摩罗什的解法:更加优秀,空间复杂度为O(1)。
思想在于,在p->next的val与当前的val相同的情况下,通过改变p->next的指向,从而让第一个开始重复的从链表断开,此时p则一直指向头部,直到出现一开始就不相等的情况就更新p(头部)。
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* dummp = new ListNode(-1);
dummp->next = head; //空节点插入链表头部
ListNode* p = dummp;
while(p->next && p->next->next){
//每次都是2个节点判断
if(p->next->val == p->next->next->val)
{
//存在重复节点
int num_flag = p->next->val; //记录第一个重复节点的值
while(p->next && p->next->val == num_flag) //循环遍历后续节点的值,并与记录的节点值比较,相同则逐个删除
{
//即将p设置为第一个不为num_flag的节点
p->next = p->next->next;
}
}
else
{
//本轮不存在重复节点,值链表指针后移
p = p->next;
}
}
return dummp->next; //返回结果
}
};