力扣刷題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;
}