个人算法成长之路二!!!定期更新一些刷题过程中个人的思路以及理解。有兴趣的朋友们可以互动交流哈~
题目:
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. 环形链表完全一样,只是返回值为节点。
需要注意的是使用快慢指针方法时,确定有环之后,还需要确定入环点。
首先,我们设定从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
};