已知链表中含有环,返回这个环的起始位置

此生再无相见时 提交于 2020-01-26 09:46:23

已知链表中含有环,返回这个环的起始位置

继上一篇博客关于双指针(快慢指针)判断是否有环,这篇关于已知链表有环,返回这个环的起始位置
先来看代码:

Node* detectCycle(Node* head) {
    Node* fast, *slow;
    fast = slow = head;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow)
            break;
    }
    
    slow = head;
    while (slow != fast) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}

一步一步来看:
首先

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

这一段代码表示,在这个有环代码中,slow与速度为其二倍的fast 相遇,并停留在相遇地点。因为上一篇解释过了,这里就不详细说了,重点看下一段

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

在这一段代码中,令slow 回到头节点,并让fast与slow以同样速度前进,当slow 与fast 再次相遇时,这个再次相遇的位置便是环的起始位置。
分析完这段代码之后让我们来通过画图方式来理解为什么再次相遇的位置就是环的起始位置(在以上提到的前提下)。
在这里插入图片描述
图中紫色为slow指针的“运动轨迹”
绿色为fast指针的运动轨迹(未重合画)
假设slow 一共走了k步,那么以其二倍速“行走”的fast指针一共走了2*k步,也就是fast指针比slow指针多走了k步(k也就是环的长度)
设相遇点距环的起点的距离为 m,那么环的起点距头结点 head 的距离为 k - m,也就是说如果从 head 前进 k - m 步就能到达环起点。
正好,如果从相遇点继续前进 k - m 步,也恰好到达环起点。
所以,只要我们把快慢指针中的任一个重新指向 head,然后两个指针同速前进,k - m 步后就会相遇,相遇之处就是环的起点了。

如果还是不是很清晰可以拿纸拿笔自己画一画,算一算
给大家看看我画的吧,嘻嘻,为了好懂就画的有点简单也有点丑
在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!