删除排序链表中的重复元素
前言
单链表由于其结构不是很完美,造成了面试官比较喜欢在单链表上出题。
删除排序链表中的重复元素Ⅰ
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。
返回同样按升序排列的结果链表。
输入:head = [1,1,2]
输出:[1,2]
看到题目我们不要慌忙去写代码,先去画画图把你所想的过程自己一步步推算下去,看看是否能行。
完整代码如下:
struct ListNode* deleteDuplicates(struct ListNode* head)
{
//当头指针为NULL,不需要排序
//或者head->next==NULL时,链表中只有一个结点,不需要进行排序
if(head==NULL||head->next==NULL)
{
return head;
}
struct ListNode*cur=head;
struct ListNode*next=head->next;
while(next!=NULL)
{
if(cur->val==next->val)
{
struct ListNode*ToDelete=next;
cur->next=next->next;
next=next->next;
free(ToDelete);
ToDelete=NULL;
}
else
{
cur=next;
next=next->next;
}
}
return head;
}
删除排序链表中的重复元素Ⅱ
我们在第一题的基础上我们升级难度,题目如下:
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中没有重复出现 的数字。
返回同样按升序排列的结果链表。
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
还是照着上题的思路,先判断有什么特殊情况
当next为NULL时,循环结束。
完整代码如下:
struct ListNode* deleteDuplicates(struct ListNode* head)
{
//特殊情况:当传进来的链表为空或者只有一个节点,就表明不可能会有重复的节点
if (head == NULL || head->next == NULL)
{
return head;
}
//创建一个哨兵位的头结点,并把它与传进来的链表进行链接,以方便插入
struct ListNode* temphead = (struct ListNode*)malloc(sizeof(struct ListNode));
temphead->next = head;
struct ListNode* prev = temphead;
struct ListNode* cur = head;
struct ListNode* next = cur->next;
while (next != NULL)
{
if (cur->val == next->val)
{
//如果相等,则判断next之后的节点是否也是该数,是就继续走,不是则跳出循环
while (next != NULL)
{
next = next->next;
if (next != NULL && next->val != cur->val)
{
break;
}
}
//从cur到next这个前闭后开的区间内,这些节点的val都是重复出现的数,要把它删除
while (next != NULL && cur->val != next->val)
{
struct ListNode* del = cur;
cur = cur->next;
free(del);
}
//到了这里next一定是与cur->val不相等了,把prev->next链接上
prev->next = next;
}
else
{
prev->next = cur;
prev = prev->next;
cur = next;
}
//如果next==NULL了,则不需要往下遍历了,不然会有空指针的问题
if (next != NULL)
{
next = next->next;
}
}
head = temphead->next;
free(temphead);
temphead=NULL;
return head;
}
感谢各位大佬拜读文章。