【链表与数组】Lintcode 103. 带环链表 II

Lintcode 103. 带环链表 II

题目描述:给定一个链表,如果链表中存在环,则返回到链表中环的起始节点,如果没有环,返回null。
在这里插入图片描述
说明:
这道题是上一道 102. 带环链表 的变形,这里除了判断是否有环之外,当有环时还需要返回环的入口地点。下面程序是基于一个结论进行实现的:最开始快指针每次走2步,慢指针每次走1步,当它俩相遇时证明有环,此时将慢指针重新拉回到链表最初的head位置,然后快慢指针同时往前走,每次走1步,这次相遇的位置就会是环的入口地点。(这个结论是可以证明的)

解题思路:

  • 使用双指针判断链表中是否有环,slow慢指针每次走一步,fast快指针每次走两步,若链表中有环,则两指针必定相遇。
  • 假设环的长度为l,环上入口距离链表头距离为a,两指针第一次相遇处距离环入口为b,则另一段环的长度为c=l-b,由于fast走过的距离是slow的两倍,则有a+l+b=2*(a+b),又有l=b+c,可得a=c,故当判断有环时(slow==fast)时,从头移动slow,同时移动fast,两指针相遇处即为环的入口。
/**
 * Definition of singly-linked-list:
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *        this->val = val;
 *        this->next = NULL;
 *     }
 * }
 */

class Solution {
    
    
public:
    /**
     * @param head: The first node of linked list.
     * @return: The node where the cycle begins. if there is no cycle, return null
     */
    ListNode * detectCycle(ListNode * head) {
    
    
        ListNode *slow, *fast;
        if (nullptr == head) {
    
    
            return nullptr;
        }
        
        slow= head;
        fast = head;
        while (nullptr != fast->next && nullptr != fast->next->next) {
    
    
            slow= slow->next;
            fast = fast->next->next;
            if (slow== fast) {
    
    //快慢指针相遇
                
                slow= head;//慢指针从头开始走
                while (slow!= fast) {
    
    //快慢指针同时移动每次走一步
                    fast = fast->next;
                    slow= slow->next;
                }
                return slow;//两指针相遇位置即为环的入口
            }
        }
        
        return nullptr;
    }
};

猜你喜欢

转载自blog.csdn.net/phdongou/article/details/113823793
今日推荐