java數據結構面試問題—快慢指針問題


上次我們學習了環形鏈表的數據結構,那么接下來我們來一起看看下面的問題,

          判斷一個單向鏈表是否是環形鏈表?

 

看到這個問題,有人就提出了進行遍歷鏈表,記住第一元素,當我們遍歷后元素再次出現則是說明是環形鏈表,如果沒有這是一個單向非環形鏈表。

 

我們來分析下上述的解決方法,我們分析這個程序的時間復雜度則是O(n)  那么是不是最優的選擇呢?

 

 我們引入新的解決思路,那就是“快慢指針”。 我們來看看接下來的解決思路,是否比上面的思路有優化的地方。

 

思路 當我們在遍歷鏈表的時候,我們設計兩個指針,分別是快指針和慢指針,塊指針每次走2步,而慢指針每次走1步,這樣的話在當我們兩個指針在鏈表中,如果會第二次相遇則說明這里面的鏈表是環形鏈表。

 

我們來用代碼實現

/**

 * 查看 鏈表中是否存在環形

 *

 * @return

 */

public boolean hasRing() {

 

if (head != null && size > 0) {

Node<T> fastTemp = head, lowTemp = head;

 

while (lowTemp.getNext() != null && fastTemp.getNext() != null) {

fastTemp = fastTemp.getNext().getNext();

lowTemp = lowTemp.getNext();

 

if (lowTemp == fastTemp) {

return true;

}

}

}

 

return false;

}

 

 

解析:定義了兩個指針節點 分別是 Node<T> fastTemp = head, lowTemp = head;

分別都是從head 開始 移動。那么下一次項目的時候,則是快指針走了兩圈,慢指針走了一圈,所一下次相遇在原地位置。

 

接下來的問題就是我們在設計快慢指針的時候,是否必須是2倍速速的快慢指針。

 

如圖所示:

 

假設: 快慢指針在C點相遇,那么相遇點在離循環點B之間是x 那么頭節點A離B的距離為 k 

 

在相遇的時候

慢指針:K + X + n*(X+Y) = m;   ①

X+Y 繞環一圈的距離;n 慢指針 總共繞了幾圈在環內

 

快指針: 

快指針是慢指針 速度的2倍,當它們相遇時 所用的時間是一樣的。那么快指針 走過得距離是2*m;

 

K+X +N*(X+Y) = 2*m;   ②

N為快指針繞過得圈數

 

② - ①  得到下面公式

(N-n)*(X+Y) = m;

接下將 ① 代入 上式得到

 (N-n)*(X+Y) = K+X+n*(X+Y);

這里X+Y 環長是個定值。 假設環長為M

(N-n)*M = K+X+n*M; ---- > 得出變形得到 K+X = (N-2*n)*M ;

 

公式 K+X = (N-2*n)*M  

 

由於我們設計的是O型循環鏈表,那么 起始就是循環點B上,則(N-2*n)*M = 0。

N = 2*n;  相遇時 快慢指針所繞 環的圈數 前者是后者的2倍,所用時間相同。這里跟環有多少節點沒有關系。

 上海尚學堂java培訓原作,陸續有數據機構等等java技術文章奉上,請多關注!

 

下面看一個例子:

          給定一個未知的長度的單向環形鏈表,如何確定鏈表中間位置的節點元素?

我們也可以使用“快慢指針”來實現,當快指針走一圈,然后停止,那么慢指針的位置則是,中間元素的位置。此時的 時間復雜O(n) = 1/2 n

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM