力扣刷题7——删除排序链表中的重复元素 II——[快慢双指针法]
- 一、博客声明
- 二、题目描述
- 三、解题思路
- 1、思路说明
- 四、解题代码(附注释)
一、博客声明
找工作逃不过刷题,为了更好的督促自己学习以及理解力扣大佬们的解题思路,开辟这个系列来记录。代码可能不是自己写的,不求方法最好,只求更多地理解大佬们的解题思路。
二、题目描述
给定一个已排序的链表的头 head
, 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
示例 1:
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
示例 2:
输入:head = [1,1,1,2,3]
输出:[2,3]
提示:
链表中节点数目在范围 [0, 300]
内
-100 <= Node.val <= 100
题目数据保证链表已经按 升序 排列
三、解题思路
1、思路说明
这题使用了快慢指针双指针去做,具体可以看下面这张图片,fast
指针跑的快,slow
跑的慢,beforeSlow
为slow
的上一个节点。通过判断nums[fast]
和nums[slow]
是否相同,期间需要定义一个标志位flag
来记录当两者不同的时候,中间是否存在相同的数,如下面遍历到第二个阶段nums[slow] = 3, nums[fast] = 4
中间就存在3
是重复数,因此要执行删除的操作。beforeSlow
存在的意义就是防止链表是重复数结尾,如果是重复数结尾,那slow
就停止了重复的第一个数上,这个数字也是要删除了,为了不重新遍历一遍,就直接让beforeSlow
是slow
的上一个节点,直接让beforeSlow->next = NULL
。
四、解题代码(附注释)
struct ListNode* deleteDuplicates(struct ListNode* head) {if(head == NULL || head->next == NULL){ //如果链表节点长度小于等于1,直接返回head;return head;}struct ListNode* preHead = malloc(sizeof(struct ListNode));//建立一个检查头preHead->val = 0;preHead->next = head;struct ListNode* slow = preHead->next;//定义慢指针struct ListNode* fast = preHead->next->next;//定义快指针struct ListNode* beforeSlow = preHead;//定义慢指针的前一个节点int flag = 0;//一个标志位,用于标记快慢指针是否正在重复while(fast){if(fast->val == slow->val){flag = 1; //快慢指针经历重复数,标志位置1fast = fast->next; // 快指针移动if(fast == NULL){ // 如果到了节点末尾,说明是重复数结尾,beforeSlow->next = NULL;//因此慢指针的前一个节点的next需要指向NULL,然后breakbreak;}continue;} else {if(flag == 0){ //标志位为0,说明不是经历重复数后判断的不同,因此慢指针移动slow = slow->next;beforeSlow = beforeSlow->next;} else {// 否则 slow = fast , 将标志位置0slow->val = fast->val;slow->next = fast->next;flag = 0;}}fast = fast->next;// 快指针移动}struct ListNode* result = preHead->next;free(preHead);return result;
}