题目描述
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
示例 1:
输入: head = [3,2,0,-4], pos = 1
输出: 返回索引为 1 的链表节点
解释: 链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入: head = [1,2], pos = 0
输出: 返回索引为 0 的链表节点
解释: 链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入: head = [1], pos = -1
输出: 返回 null
解释: 链表中没有环。
提示:
链表中节点的数目范围是 [0, ]
<= Node.val <=
pos 为 -1 或者链表中的一个有效索引 。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/li… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
数学思想:
假定有一个环形链表,如图
有两个指针起始均指向链表头部,慢指针每次位移量为1,快指针每次位移量为2,图中位移量A为快慢指针共同移动的路程,设为A,快慢指针,某一时刻在45处相遇,此时快慢指针共同经过的路程设为B,从相遇点到入环点的路程设为C,此时慢指针走过的距离为A+B,快指针走过的短距离为A+n(B+C)+B,n为快慢指针相遇时快指针多跑的圈数, 因为快指针速度是慢指针的两倍,所以产生等式:2(A+B)=A+n(B+C)+B变形为:A=(N-1)(B+C)+C,我们知道B+C的含义为一圈,一圈的位移量是0,于是等式变为A=(N-1)×0+C 推出A=C所以,当我们从相遇点开始走,让第三个指针同时从链表头开始走,当两个指针相遇就是链表的入环点
解题方案:定义两个指针,初始均指向链表头地址,快指针每次移动两个位移量,慢指针每次移动一个位移量,如果存在指针指向null则结束循环返回false(链表非闭合),如果两个指针存在相等的时候,则说明链表为闭合链表,此时定义第三个指针指向链表头部,同时开始位移,直到相等,相等值即为链表的入环处
解题代码:
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head 链表头指针
* @return {ListNode}
*/
var detectCycle = function(head) {
//头指针为空==>链表非环形链表
if(!head) return null;
let pre = head;//慢指针
let cur = head;//快指针
//如果当前位置或下一个位置指向空,即链表有终点==>非环形链表
while(cur && cur.next){
pre = pre.next;//慢指针走一步
cur = cur.next.next;//快指针走两步
//当两个指针相等说明指针相遇==>链表为环形链表
if(pre === cur){
//定义头结点
let res = head;
//让头结点与当前指针节点同时移动一个单位
//当二者相等即指针相遇即为环形链表的入环处
//跳出循环返回当前指针位置
while(res !== cur){
res = res.next;
cur = cur.next;
};
return res;
}
};
return null;
};