1. 程式人生 > >判斷連結串列是否有環---leetcode題目

判斷連結串列是否有環---leetcode題目

分享2道leetcode題目(判斷連結串列是否有環以及找出環的入口點)

141. Linked List Cycle

Given a linked list, determine if it has a cycle in it.

142. Linked List Cycle II

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

第一題就是給你一個連結串列,讓你判斷是否有環,如果有返回true,否則返回false

解法過程

1.首先說明連結串列環的構成:

連結串列的某個節點的next指標指向到前面的節點,如以下所示
(0->1->2->3->4->5->6->3->4…)

這樣子在6節點的後面就會形成無窮無盡的連結串列,就形成環了。

2.設定分別設定一個快慢指標,快指標執行速度是慢指標的2倍,如果該連結串列是個環,則快慢指標必相遇,並且相遇是慢指標並沒有跑完整個連結串列長度

快指標設定fast = fast.next.next;

慢指標設定slow = slow.next;

public boolean hasCycle(ListNode head) {
       if
(head == null || (head.next == null)) { return false; } ListNode slow = head; ListNode fast = head; //如果快慢指標相遇,則存在環 while(fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if(fast == slow) { return
true; } } return false; }

第二題就是給你一個連結串列,如果這個連結串列有環,則返回環的入口點,如果沒有返回null

解法過程
先列出一個有環的連結串列:
1->2->3->4->5->6->7->8->9->10->3->4…

那答案就是這個連結串列返回3這個節點

1.順著第一步分析,快慢指標相遇點是在9這個節點,如果這時候在9這處放置一個指標,在頭節點處放置一個指標,讓他們同時以相同的速度移動,則很恰巧他們是在3這個環的入口點相遇,這是巧合嗎。接下來就要驗證該方法是否可行。

設定連結串列長度為L,入口點距離頭節點距離為a,快慢指標相遇點距離入口點為b,滿指標速度為s,環的長度為r,則可以得到以下公式:

2s = s + nr (n為環的圈數)

s = a + b (慢指標從頭節點走到相遇點)

r = L - a

2.則我們可以把公式變形成如下

a + b = nr

a = nr -b

a = (n-1)r + r - b

a = (n-1)r + (L -a -b)

這個公式可以得出a就是環入口距離頭節點的距離,(n-1)r是(n-1)圈的環,(L-a-b)其實就是相遇點到環入口的距離

那其實可以得出如果一個指標從相遇點出發,則一定會跟一個從頭指標出發的指標相遇,並且相遇點 就是環的入口點

3.那麼解法就很簡單了

public ListNode detectCycle(ListNode head) {
        if(head == null || (head.next == null)) {
           return null;
       }
       ListNode slow = head,fast = head;
       ListNode start = head;
       ListNode end = null;
       //快慢指標找到相遇點
       while(fast != null && fast.next != null) {
           slow = slow.next;
           fast = fast.next.next;
            if(fast == slow) {
               end = fast;
               break;
           }
       }
       if(end == null || end.next == null ){
           return null;
       }
       //這時重新在相遇點跟head出設定指標,然後同時走一步,則相遇點就是環入口
       while(start != end) {
           start = start.next;
           end = end.next;
       }
       return start;
    }

謝謝欣賞!