1. 程式人生 > 實用技巧 >快慢雙指標法

快慢雙指標法

介紹

快慢雙指標是雙指標問題的一種解決方案,主要用於解決連結串列相關的題目,而左右指標那種滑動視窗的演算法主要是用於解決陣列問題

應用

  • 快慢雙指標可以用來判定連結串列中是否存在環
    一般而言,如果連結串列中存在環路,那麼對於單鏈表的遍歷就會陷入死迴圈,可以使用快慢雙指標去遍歷該連結串列,慢指標一步一步走,快指標一次走兩步;
    那麼如果快指標最終走到null節點,那麼就是遍歷完成;
    如果存在環路,那麼快慢指標最終一定會相遇,因為快指標始終快於慢指標一倍的距離
boolean hasCycle(ListNode head) {
    ListNode fast, slow;
    fast = slow = head;
    while(fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        
        if (fast == slow)
            return true;
    }
    return false;
}
  • 找到連結串列中環路的起點
    當快慢指標第一次相遇的時候,就可以確定連結串列中存在環路,如果讓其中一個節點回到起點再讓快慢指標以同樣速度前進,那麼再次相遇就是環起點
ListNode detectCycle(ListNode head) {
    ListNode fast, slow;
    fast = slow = head;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow)
            break;
    }
    
    slow = head;
    while (slow != fast) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}
  • 尋找連結串列中點
    我們可以讓快指標一次前進兩步,慢指標一次前進一步,當快指標到達連結串列盡頭時,慢指標就處於連結串列的中間位置。
ListNode slow, fast;
slow = fast = head;
while (fast != null && fast.next != null) {
    fast = fast.next.next;
    slow = slow.next;
}
// slow 就在中間位置
return slow;

當程式結束時,如果連結串列的長度是奇數時,slow 恰巧停在中點位置;如果長度是偶數,slow 最終的位置是中間偏右;可以利用這個方法去進行歸併排序

  • 尋找連結串列的倒數第k個節點
    讓快指標先走 k 步,然後快慢指標開始同速前進。這樣當快指標走到連結串列末尾 null 時,慢指標所在的位置就是倒數第 k 個連結串列節點(假設 k 不會超過連結串列長度)
ListNode slow, fast;
slow = fast = head;
while (k-- > 0) 
    fast = fast.next;
 
while (fast != null) {
    slow = slow.next;
    fast = fast.next;
}
return slow;