描述
給定一個鏈表,如果鏈表中存在環(huán),則返回到鏈表中環(huán)的起始節(jié)點,如果沒有環(huán),返回null。
樣例
給出 -21->10->4->5, tail connects to node index 1,返回10
挑戰(zhàn)
不使用額外的空間
思路
本題更像一道數(shù)學題,判斷是否有環(huán)用典型的快慢指針方法就可以解決,此處主要說怎么找到環(huán)的入口,設(shè)環(huán)的長度為 r,快指針的速度是慢指針的 2 倍,兩個指針在第k步(可能已經(jīng)繞環(huán)若干圈)相遇時,2k - k = nr 即 k = nr,設(shè)鏈表起始點到環(huán)的入口點(包括環(huán)的入口點)的距離是 s ,從環(huán)的起始點開始(不包含起始點)到相遇點的距離是 m (注意此處的 m 可能是包含若干個整圈距離再加上一個不足圈的環(huán)入口點到相遇點的距離) ,m + s = k 即 s = k - m => s = nr - m,那我們可以得出結(jié)論從快慢指針的相遇點往前出發(fā)走 s 步正好是環(huán)入口的上一個結(jié)點
代碼
/**
* Definition for ListNode.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int val) {
* this.val = val;
* this.next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
// 空結(jié)點或者不帶環(huán)的單獨結(jié)點 return null
if (head == null || head.next == null) {
return null;
}
ListNode fast, slow;
fast = head.next;
slow = head;
// 先判斷是否存在環(huán)
while (fast != slow) {
if (fast == null || fast.next == null) {
return null;
}
fast = fast.next.next;
slow = slow.next;
}
// slow 和 head 正好差一個結(jié)點,當 head 是環(huán)入口時,slow 是環(huán)入口的上一個結(jié)點
while (head != slow.next) {
head = head.next;
slow = slow.next;
}
// 也可寫 return slow.next;
return head;
}
}