[LeetCode]93. Linked List Cycle II查找链表中环的起始节点

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.

Follow up:
Can you solve it without using extra space?

 

Subscribe to see which companies asked this question

 
解法:这道题是题目Linked List Cycle判断链表是否有环的扩展,要求返回环的起始位置或者NULL。同上一题,我们依然先用快慢指针方法判断链表是否存在环,如果存在则获得两个指针第一次相交的位置。可以证明,这个位置距离环的起始位置和链表头节点距离环的起始位置的节点个数是一样的。因此我们只要将两个指针分别设置为从头节点和这个交点节点开始,一步步前移,然后两个指针的第一次相交位置即是环的起始节点。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if (head == NULL || head->next == NULL) return NULL;
        ListNode *slow = head, *fast = head;
        while (fast->next != NULL && fast->next->next != NULL) { // 判断是否有环
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) break;
        }
        if (fast->next == NULL || fast->next->next == NULL) return NULL;
        slow = head;
        while (slow != fast) {
            slow = slow->next;
            fast = fast->next;
        }
        return slow;
    }
};

说明:假设环外有n1个节点,环有n2个节点,在slow指针走n1步到达环的入口节点时,fast指针走了2n1步,此时它在环中的位置是距离入口节点有(2n1-n1)%n2个节点,即在入口节点前面n1%n2个节点处。也就是相当于fast指针落后slow指针n2-n1%n2个节点。fast指针相对slow指针的速度是1,因此在走n2-n1%n2步后两个指针就会相遇,此时slow指针从入口节点往前移动了n2-n1%n2个节点。因此相交点距离入口节点的距离就是n2-(n2-n1%n2)=n1%n2个节点。此时slow指针从头节点开始,fast指针从交点开始,各自以1的速度前移,第一次相交位置必定是入口节点。fast指针要么是走了n1%n2步(n1<n2的情况),要么是走了n1%n2+kn2步(k为正整数)(n1>n2的情况,即fast指针在环中转了几圈后再走了n1%n2步)。

关于单链表中的环的更多问题,请参考http://www.cnblogs.com/hiddenfox/p/3408931.htmlhttp://www.cnblogs.com/wuyuegb2312/p/3183214.html

posted @ 2015-11-18 10:38  AprilCheny  阅读(673)  评论(0编辑  收藏  举报