1. 程式人生 > 其它 >雙指標演算法詳解

雙指標演算法詳解

雙指標演算法詳解

參考連結

練習題

相關連結

什麼是雙指標

雙指標,指的是在遍歷物件的過程中,不是普通的使用單個指標[或者稱之為變數]進行訪問,而是使用兩個相同方向(快慢指標)或者相反方向(對撞指標)的指標進行掃描,從而達到相應的目的。

換言之,雙指標法充分使用了陣列有序這一特徵,從而在某些情況下能夠簡化一些運算。

LeetCode 題庫中,關於雙指標的問題還是挺多的。

雙指標

雙指標從廣義上來說,是指用兩個變數線上性結構上遍歷而解決的問題。狹義上說,

  • 對於陣列,指兩個變數在陣列上相向移動解決的問題;
  • 對於連結串列,指兩個變數在連結串列上同向移動解決的問題,也稱為「快慢指標」問題。

雙指標演算法通常不難,雙指標演算法是基於暴力解法的優化,它們是很好的學習演算法的入門問題,讓我們開始學習雙指標演算法之旅吧。

快慢指標(Fast & Slow pointers)

基本原理及應用場景

快慢指標方法,又稱為龜兔賽跑演算法,其基本思想就是使用兩個移動速度不同的指標(快指標是慢指標的X倍,X > 1)在陣列或連結串列等序列結構上移動。這種方法對於處理「環形」

連結串列或陣列非常有用。以連結串列為例,通過以不同的速度移動,我們可以證明如果連結串列中存在環,則兩個指標必定會相遇,當兩個指標均處在環中時,快指標會追上慢指標(如下圖所示)。

為什麼說快指標一定會追上慢指標?,即快慢指標一定會相遇?

這個問題你可以用數學歸納法來思考。首先,由於連結串列是個環,所以相遇的過程可以看作是快指標從後邊追趕慢指標的過程。那麼做如下思考:當快慢兩個指標均落入環中之後【一直往下走兩個指標必定均會落入環中】,落入環中時就一定會是如下情況中的一種,我們歸納討論

HINT: 這裡我們不考慮當快慢指標均落入環中的那一刻就是在相同位置的情況,那種情況只可能發生在快慢指標的速率是一樣的,那也就不能稱之為快慢指標了,與我們的架設前提不服,因此在此不做討論

1:快指標與慢指標之間差一步。此時繼續往後走,慢指標前進一步,快指標前進兩步,兩者相遇。
2:快指標與慢指標之間差兩步。此時繼續往後走,慢指標前進一步,快指標前進兩步,兩者之間相差一步,轉化為第一種情況。
3:快指標與慢指標之間差N步。此時繼續往後走,慢指標前進一步,快指標前進兩步,兩者之間相差(N+1-2)-> N-1步。

因此,此題得證。所以快指標必然與慢指標相遇。

我們簡化為如下的數學模型,假設快慢指標在綠點相遇;假定快指標在環中繞了P圈在綠點與慢指標相遇,慢指標在環中繞了Q圈在綠點與快指標相遇。

我們可以計算出:

快指標走的路程為:S(快指標路程) = A + (P+1)*B + P*C

慢指標走的路程為:S(慢指標路程) = A + (Q+1)*B + Q*C

又因為快指標是慢指標速率的X倍,因此可得出:

S(快指標路程) = X*S(慢指標路程),即

A + (P+1)*B + P*C = X*{A + (Q+1)*B + Q*C}

P>Q && P,Q均要儘量小[因為是第一次相遇]

當快指標的速率為慢指標的速率的兩倍時,即X = 2

(P-2Q)(B+C) = A+B ==> (P-2Q-1)(B+C) + C = A

假定環長為D,即D=B+C,則:

(P-2Q-1)D + C = AP>Q && P,Q均要儘量小[因為是第一次相遇]

當要查詢環的起點時,就需要用到上述結論;即當找到相遇節點之後,用一個指標從相遇節點開始往後走,一個節點從頭開始走,當兩者相等時候即為連結串列環的起點。

通過上面的結論我們可以輕鬆解決,判斷連結串列中是否有環以及如何找到對應環的起始點;並且利用快慢指標也能快速找到等分點(最經典的就是二等分點即中點)等問題,可以再刷幾道題實戰一下,雙指標演算法基本原理和實踐

歡迎關注H尋夢人公眾號,更多精彩博文!!!