环形链表II
1、題目描述
給定一個鏈表,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null。
為了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鏈表中沒有環。
說明:不允許修改給定的鏈表。
示例 1:
輸入:head = [3,2,0,-4], pos = 1 輸出:tail connects to node index 1 解釋:鏈表中有一個環,其尾部連接到第二個節點。
示例 2:
示例 3:
2、解法
2.1 Floyd 算法
想法
當然一個跑得快的人和一個跑得慢的人在一個圓形的賽道上賽跑,會發生什么?在某一個時刻,跑得快的人一定會從后面趕上跑得慢的人。
算法
Floyd 的算法被劃分成兩個不同的 階段 。在第一階段,找出列表中是否有環,如果沒有環,可以直接返回 null 并退出。否則,用 相遇節點 來找到環的入口。
階段 1
這里我們初始化兩個指針 - 快指針和慢指針。我們每次移動慢指針一步、快指針兩步,直到快指針無法繼續往前移動。如果在某次移動后,快慢指針指向了同一個節點,我們就返回它。否則,我們繼續,直到 while 循環終止且沒有返回任何節點,這種情況說明沒有成環,我們返回 null 。
下圖說明了這個算法的工作方式:
階段 2
給定階段 1 找到的相遇點,階段 2 將找到環的入口。首先我們初始化額外的兩個指針: ptr1 ,指向鏈表的頭, ptr2 指向相遇點。然后,我們每次將它們往前移動一步,直到它們相遇,它們相遇的點就是環的入口,返回這個節點。
下面的圖將更好的幫助理解和證明這個方法的正確性。
我們利用已知的條件:慢指針移動 1 步,快指針移動 2 步,來說明它們相遇在環的入口處。(下面證明中的 tortoise 表示慢指針,hare 表示快指針)
因為 F=b,指針從 h 點出發和從鏈表的頭出發,最后會遍歷相同數目的節點后在環的入口處相遇。
代碼實現如下:
public ListNode detectCycle(ListNode head) {if(head == null || head.next==null) {return null;}ListNode slow = head.next, fast = head.next.next;while(fast != null) {if(fast.next == null) {return null;}if(slow == fast) {//快慢指針相遇了break;}slow = slow.next;fast = fast.next.next;}//無環if(fast == null) {return null;}//有環ListNode start = head;while(start != slow) {start = start.next;slow = slow.next;}return slow;}總結
- 上一篇: 淡菜红枣粥的功效与作用、禁忌和食用方法
- 下一篇: 夏橙的功效与作用、禁忌和食用方法