1. 程式人生 > 遊戲 >《消逝的光芒2》前幾個DLC地點不會離城市太遠

《消逝的光芒2》前幾個DLC地點不會離城市太遠

142.環形連結串列 II

方式一:雜湊表

我們遍歷連結串列中的每個節點,並將它記錄下來;一旦遇到了此前遍歷過的節點,就可以判定連結串列中存在環。藉助雜湊表可以很方便地實現。

public class Solution {
    public ListNode detectCycle(ListNode head) {
        Set<ListNode> set = new HashSet<ListNode>();
        while (head != null) {
            if (set.contains(head)) {
                return head;
            } else {
                set.add(head);
            }
            head = head.next;
        }
        return null;
    }
}

方式二:快慢指標

這類連結串列題目一般都是使用雙指標法解決的,例如尋找距離尾部第K個節點、尋找環入口、尋找公共尾部入口等。

雙指標第一次相遇:

設 fast 和 slow 指向連結串列頭部 head,fast走2步,slow走1步

  1. 第一種結果:fast 指標走到連結串列末端,表示連結串列無環,返回 null

  2. 第二種結果:當 fast == null時,兩指標第一次在環裡相遇

    1. 設連結串列一共有 x 個結點,其中連結串列頭部到環入口有 a 個結點,連結串列環有 b 個結點
      1. fast 的步數是 slow 步數的 2 倍 f = 2s
      2. fast 比 slow 多走了 n 個 環的長度 f = s + nb
    1. 有上式可得
      1. f = 2nb,s = nb

雙指標第二次相遇:

  1. slow指標位置不變 ,將fast指標重新指向連結串列頭部節點;slow和fast同時每輪向前走111步;
  2. 當 fast 指標走到f=af = af=a 步時,slow 指標走到步s=a+nbs = a+nbs=a+nb,此時兩指標重合,並同時指向連結串列環入口 。
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head, slow = head;
        while (true) {
            if (fast == null || fast.next == null) return null;
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) break;
        }
        fast = head;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.nxet;
        }
        return fast;
    }
}