给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

说明:不允许修改给定的链表。

进阶:
你是否可以不用额外空间解决此题?

 


 

 

//章节 - 链表    
//二、双指针技巧
//2.环形链表 II
/*
算法思想:
    还是要设快慢指针,不过这次要记录两个指针相遇的位置,当两个指针相遇了后,让其一指针从链表头开始,此时再相遇的位置就是链表中环的起始位置。
    为什么慢指针从链表头开始,再相遇的位置就是链表中环的起始位置?
    可以证明,这个位置距离环的起始位置和链表头节点距离环的起始位置的节点个数是一样的。因此我们只要将两个指针分别设置为从头节点和这个交点节点开始,一步步前移,然后两个指针的第一次相交位置即是环的起始节点。
*/
//算法实现:
/**
 * 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) {
        ListNode *slow = head, *fast = head;
        while (fast != NULL && fast->next != NULL) {    //找到第一次相遇的位置
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) 
                break;
        }
        if (fast == NULL || fast->next == NULL) //如果链表无环,则返回 null。
            return NULL;
        slow = head;    
        while (slow != fast) {  //慢指针从链表头开始,再相遇的位置就是链表中环的起始位置。
            slow = slow->next;
            fast = fast->next;
        }
        return fast;
    }
};