[路飞]_算法成长之路一,环形链表II

954 阅读2分钟

个人算法成长之路二!!!定期更新一些刷题过程中个人的思路以及理解。有兴趣的朋友们可以互动交流哈~

题目:

leetcode-142. 环形链表 II

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

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 不允许修改 链表。  

示例 1:

输入: head = [3,2,0,-4], pos = 1
输出: 返回索引为 1 的链表节点
解释: 链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入: head = [1], pos = -1
输出: 返回 null
解释: 链表中没有环。

解题思路:

这道题几乎和leetcode- 141. 环形链表完全一样,只是返回值为节点。

需要注意的是使用快慢指针方法时,确定有环之后,还需要确定入环点。

无标题.png

首先,我们设定从head到入环点距离为a,入环点到首次相遇点距离为b,首次相遇点到入环点距离为c; 假设slow进入环后,走了b距离,和fast相遇,假设此时fast已经做过了n圈,那么fast走过的距离为 a+n(b+c)+b = a+(n+1)b +nc

又知fast速度是slow速度的2倍,所以,2(a+b) = a+(n+1)b +nc ===> a = (n-1)(b+c) + c 因此,相遇点到入环点的距离加上(n-1)圈恰好等于head到入环点的距离。 到了这里,一切都变得容易了,我们可以让fast从头开始,和slow以相同的速度向前移动,slow和fast相遇点即为入环点。

var detectCycle = function(head) {
    let fast = head;
    let slow = head;
    while(fast) {
        slow = slow.next;
        if(fast.next) {
            fast = fast.next.next
        }else{
            return null
        }
        if (fast === slow) {//有环
            let fast = head;
          	//快指针指向头节点,然后每次快慢指针各走一步直到相遇,相遇的节点就是入环节点
            while (fast !== slow) {
                fast = fast.next;
                slow = slow.next;
            }
            return fast;
        }
    }
    return null
};