Leetcode解題思想總結篇:雙指針
1概念
雙指針:快慢指針。
快指針在每一步走的步長要比慢指針一步走的步長要多。快指針通常的步速是慢指針的2倍。
在循環中的指針移動通常為:
faster = faster.next.next; slower = slower.next;
2 應用
2.1. 用來判斷鏈表是否有環以及尋找環入口
- Linked List Cycle
- Linked List Cycle II
是否有環:快慢指針思想,注意循環條件:(fast != null) && (fast.next != null)
尋找環的入口:快慢指針相遇的時候,distance(fast指針) = 2 * distance(slow指針),可以推導出,只要把fast重新指向頭結點,兩個指針以一樣的速度走,相遇的時候,便是環的入口。
2.2.數組尋找范圍
- Summary Ranges
范圍的尋找,用2個指針:start ,end來記錄范圍。注意循環條件和判斷條件:(end + 1 < len) && (nums[end + 1] == nums[end] + 1)
2.3.鏈表或者數組中移除重復的元素
- Remove Duplicates from Sorted List I
- Remove Duplicates from Sorted List II
Sorted List I用兩個指針一前一后指向鏈表。維護兩個指針:
tail一個指向當前不重復的最后一個元素,pCur一個進行依次掃描,遇到不重復的則更新第一個指針,繼續掃描,否則就把前面指針指向當前元素的下一個(即把當前元素從鏈表中刪除)。
Sorted List II 維護兩個指針:
prev前驅指針指向上一個不重復的元素pCur遍歷指針
思路類似Sorted List I,細節更多。
尋找不重復的元素 while循環條件pCur.next != null && prev.next.val == pCur.next.val
Array數組中的解題思想一樣:
index指向上當前不重復的最后一個元素i遍歷數組
2.4. 用來找中點或中位數
2.5. 倒數第n個
題目中含有:倒數第n個,那么設置快指針步長為n,然后快慢指針同時以同一速度走,用慢指針尋找倒數第n個
2.6. 拆分鏈表
Partition List
給定一個x的值,小於x都放在大於等於x的前面,並且不改變鏈表之間node原始的相對位置。example中 4->3->5都是大於等3的數,這保持了他們原來的相對位置。
使用鏈表最常用的雙指針:
- 一個指向當前小於x的最后一個元素
- 一個進行往前掃描。如果元素大於x,那么繼續前進,否則,要把元素移到前面,並更新第一個指針。
Reorder List
思路:
1.利用快慢兩個指針將鏈表一分為二;
2.針對第二個子鏈表求倒序;
3.利用merge思想將兩個子鏈表合並。
3 相關題目
- Summary Ranges
- Linked List Cycle
- Linked List Cycle II
- Remove Duplicates from Sorted List I
- Remove Duplicates from Sorted List II
- Remove Duplicates from Sorted Array I
- Remove Duplicates from Sorted Array II
- Partition List
- Intersection of Two Linked Lists
- Remove Nth Node From End of List
- Reorder List
- Delete Node in a Linked List
4 注意
- 通常需要特別留意鏈表長度的奇偶性
- 如果快指針步速為慢指針步速2倍,循環條件為:
faster.next!=null && faster.next.next!=null - 當自行設置快指針步長時, 要考慮步長值等於鏈表長度的特殊情況
- 查找倒數第n個時,如果要求刪除鏈表元素時,不要忘記記錄應被刪除元素的前一個元素
- 對於鏈表的題目,常常都會用到
Two Pointers的思想。鏈表注意構建dummy頭結點。在Java中,由於沒有free函數,所以在刪除一個節點的時候,無法用node = null來刪除一個節點,需要用前一個節點來指向刪除節點的下一個prev.next = node.next這樣來刪除node節點。
