【Leetcode】142.Linked List Cycle II

於淼發表於2018-02-28

Question:

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Tips:

給定一個連結串列,如果連結串列中有環,返回環開始的結點。如果連結串列無環 返回null。

思路:

之前141題(連結),判斷連結串列中是否有環,返回布林型別的變數。本題還需要返回環開始的結點。解決過程分為以下幾步。

(1)設定兩個速度不同的指標,fast與slow。fast的速度是slow的二倍。

fast = fast.next.next;
slow = slow.next;

當兩個指標相遇,證明連結串列存在結點,否則,fast指標先遇到null證明連結串列內無環。

(2)在兩個指標相遇處切開,則變成了求兩個單連結串列第一個公共結點的問題160(連結)。

slow路程:S1=L+a;(L連結串列無環部分長度,a為slow指標走過的環內的弧長)

fast路程:S2=L+a+n*k;(n表示環內結點長度,k表示 fast指標走過的環的圈數)

路程=速度*時間。slow的速度*2=fast的速度。相遇代表時間相等。則S1*2=S2。

2(L+a)=L+a+n*k; ==> L+a=n*k

          ==> L=n*k-a;

從上面的分析可以看出,連結串列中,不在環內的長度L=環的長度n - slow走過的弧長。

這時,新建一個指標,從head開始向後移動,相遇處的指標繼續後移,當兩個指標再次相遇,則該節點是環開始的第一個結點。

程式碼:

public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        ListNode meet = null;
        while (fast != null) {
            if (fast.next != null) {
                fast = fast.next;
                if (fast.next != null) {
                    fast = fast.next;
                    slow = slow.next;
                    if (fast == slow) {
                        //fast與slow相遇
                        meet = slow;
                        break;
                    }
                } else
                    return null;
            } else
                return null;
        }
        ListNode haha = head;
        //迴圈結束,兩個指標均指向環開始的結點。
        while (haha != meet) {
            haha = haha.next;
            meet = meet.next;
        }

        return meet;
    }

測試程式碼:

public static void main(String[] args) {
        ListNode head1 = new ListNode(1);
        ListNode head2 = new ListNode(2);
        ListNode head3 = new ListNode(3);
        ListNode head4 = new ListNode(4);
        ListNode head5 = new ListNode(5);
        ListNode head6 = new ListNode(6);
        head1.next = head2;
        head2.next = head3;
        head3.next = head4;
        head4.next = head5;
        head5.next = head6;
        head6.next = head3;
        L142LinkedListCycleII l142 = new L142LinkedListCycleII();
        ListNode head = l142.detectCycle(head1);
        if(head!=null){
            System.out.println(head.val);
        }else{
            System.out.println("Null");
        }
        
    }

 

相關文章