题解 | #链表中环的入口结点#

链表中环的入口结点

http://www.nowcoder.com/practice/253d2c59ec3e4bc68da16833f79a38e4

方便分析作图如下,假设a是链表头节点,b是链表中环的入口节点,c是快慢指针相遇的节点。

三段路径长度按顺时针分别称为ab,bc,cb。链表中环长度为s = bc + cb。

alt

我们需要计算,在c点相遇的时候,快慢指针分别走了多远?利用快慢指针长度的两倍关系去求解问题。

快指针到c点走过的长度 s1 = ab + bc + n * s = ab + bc + n * (bc + cb)

快指针走的距离包括ab+bc的距离,再加上在圆环中环绕圈数的距离。

那么慢指针的长度如何计算?他在环中也走了多少圈?

这就需要理解一个概念:

从慢指针进入环时,到快慢指针相遇,慢指针走过的距离是一定小于等于环的大小。(如果整个链表是一个环,则慢指针走过距离等于环大小) 慢指针进入环后,可以看成快指针在后面追赶慢指针。

最好情况快指针就在b的左侧,移动一步两者便相遇。 最差情况为快指针在b的右侧,需要多绕不到一圈的距离。 分析最差情况:假设慢指针走了一整圈环,回到b点时快指针才追上,慢指针移动长度为s,快指针移动长度则为2s-1。但实际上快指针速度是慢指针两倍,即实际应走距离为2s。可以反证出在慢指针走完一圈之前,快指针必然追上慢指针。

理解了上述概念,可以很快得出,慢指针长度 s2 = ab + bc

已知了快指针是慢指针两倍,即 2 *(ab + bc) = ab + bc + n * (bc + cb)

推出:ab = (n-1) * (bc + cb) + cb

含义为:链表头到环入口的距离=相遇点到环入口的距离+(n-1)圈环长度

分析到这里,其实已经得出答案了。两个链表相遇后,一个指针指向相遇的位置,一个指针指到链表的头节点。两个指针均向后移动,判断当两者相同时,该节点便是链表到环的入口节点。

代码参考:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        ListNode* fast = pHead;
        ListNode* slow = pHead;
        while(fast != nullptr && fast->next != nullptr){
            slow = slow->next;
            fast = fast->next->next;
            if(fast == slow){
                break;
            }
        }
        if(fast==nullptr || fast->next == nullptr) return nullptr;
        fast = pHead;
        while(fast != slow){
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }
};
全部评论

相关推荐

12-20 11:26
复旦大学 Java
点赞 评论 收藏
分享
12-19 22:04
武汉大学 Java
点赞 评论 收藏
分享
稽鱼:简历好丑啊,换个模板,别用红色字体
点赞 评论 收藏
分享
10-31 13:04
南华大学 Java
嵌入式的小白:很多面试,面试前不会去打扰cto的,但一般cto不会在这些小事上刷人,只能说这个cto比较操心,啥重要不重要,紧急不紧急的,估计都会过问,平淡看待吧
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务