淺談雙指針技巧(三)利用快慢指針,查找鏈表中指定位置節點

前面兩篇文章主要介紹了,快慢指針在鏈表環中的應用。除此之外,我們還常常利用快慢指針來查找單向鏈表中指定位置的節點。
常見的經典題目有:
1、查找倒數i位置的的節點
2、查找中間節點
我們依次來看
一、查找快慢指針查找單鏈表中位於倒數第i個位置的元素
力扣 劍指 Offer 22. 鏈表中倒數第k個節點 (https://leetcode.cn/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/)
如果沒有提前做過準備,想要解決類似問題,只能通過緩存等方式來解決。但是通過快慢指針,可以很巧妙的解決該問題。
思路是這樣的:(防盜連接:本文首發自http://www.cnblogs.com/jilodream/ )
快慢指針同時指向head節點。接着慢指針不動,快指針向前移動i步。之後快慢指針同速前移動。直至快指針先到終點,此時慢指針,所處的位置就是倒數第i個節點的位置。
就像下圖,假設右側小人先跑40m,隨後兩者同速前進,則左側小人距離右側小人始終爲40m。這樣當右側小人到達終點時,左側小人的位置恰好爲倒數40m處:

 代碼也很簡單:

 1     public ListNode getKthFromEnd(ListNode head, int k) {
 2         ListNode fast = head;
 3         ListNode tail = head;
 4         for (int i = 0; i < k-1; i++) {
 5             fast = fast.next;
 6         }
 7         while (fast.next != null) {
 8             fast = fast.next;
 9             tail = tail.next;
10         }
11         return tail;
12     }

 這個場景其實除了雙指針的解法,還可以通過遞歸出棧的方式解決,感興趣的同學可以自己想想

二、查找鏈表中間位置的節點
力扣 876. 鏈表的中間結點 (https://leetcode.cn/problems/middle-of-the-linked-list/)
此題與上題類似,仍然可以採用快慢指針的形式。
區別是不再同速保持固定距離,而是快指針每次走兩步,慢指針走一步。
這樣假設快指針遍歷了2N個節點,慢指針就是便宜了N個節點。
如果你自己考慮這個問題,你會發現事情沒有這麼簡單:
這裏會涉及到兩個問題:(防盜連接:本文首發自http://www.cnblogs.com/jilodream/ )
1、鏈表長度是不是偶數。
2、鏈表如果是偶數,那麼中間節點應該是中間位置左側節點 還是右側節點。
如果鏈表長度奇數的話,那麼要注意快指針最後一次移動是不能走兩步的。
如果鏈表長度是偶數的話,我們取中間位置的右側節點。代碼如下:

 1     public ListNode middleNode(ListNode head) {
 2         ListNode fast = head;
 3         ListNode low = head;
 4         while (true) {
 5             if (fast.next == null) {
 6                 return low;
 7             }
 8             low = low.next;
 9             fast = fast.next;
10             if (fast.next != null) {
11                 fast = fast.next;
12             }
13         }
14     }

 細想一下,這種思路其實除了可以找到中間節點位置,還可以找到1/3處節點位置,1/5處節點位置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章