Linked List Cycle II

Question

Description

Given a linked list, return the node where the cycle begins.

If there is no cycle, returnnull.

Example

Given-21->10->4->5, tail connects to node index 1,return10

Challenge

Follow up:

Can you solve it without using extra space?

题解思路

可以先判断Linked List是否有Cycle,利用two pointers可以很快得到。接下来就要分析,快慢指针第一次相遇时,位置、步数和环的关系。

    a            b
A ------ B --------+
         |         |
       c |         |
         +-------- C



* A: 起始点
* B: Cycle Begins
* C: 1st 快慢指针相遇点


* A->B: a
* B->C: b
* C->B: c
* 环的长度 (b+c) 为 R

第一次相遇时,慢指针所走步数为

a + b

快指针走的步数为

a + b + nR

我们知道快指针是慢指针速度的2倍,因此

2(a + b) = a + b + nR

那么

a + b = nR

同时

b + c = R

所以

a = (n - 1)R + c;

也就是说,从A点和C点同时出发,以相同的速度前进,那么下一次相遇的位置将是B。

参考 LeetCode: https://leetcode.com/articles/linked-list-cycle/

源代码

Easier to understand:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
         if (head == null || head.next == null) return null;
        ListNode slow = head;
        ListNode fast = head;
        while (slow != null && fast != null) {
            slow = slow.next;
            if (fast.next == null) return null;
            fast = fast.next.next;
            if (slow == fast) break;
        }
        slow = head;
        if (fast != null) {
            while (slow != fast) {
                slow = slow.next;
                fast = fast.next;
            }
            return slow;
        }
        return null;
    }
}

Preferred Implementation:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    private ListNode answer = null;
    public ListNode detectCycle(ListNode head) {
        if(head == null || head.next == null){
            return null;
        }
        ListNode slow = head;
        ListNode fast = head;

        while(fast != null && fast.next != null) {

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

            if (slow == fast) {
                break;
            }
        }
        if (fast == slow) {
            slow = head;
            while (fast != slow) {
                fast = fast.next;
                slow = slow.next;
            }
            return slow;
        }
        return null;
    }
}

Harder to understand with pointer corner cases

/**
 * 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) {
        if (head == null || head.next==null) {
            return null;
        }

        ListNode fast, slow;
        fast = head.next;
        slow = head;
        while (fast != slow) {
            if(fast==null || fast.next==null)
                return null;
            fast = fast.next.next;
            slow = slow.next;
        } 

        while (head != slow.next) {
            head = head.next;
            slow = slow.next;
        }
        return head;
    }
}

Last updated