23.链表中环的入口结点
题目
找出链表中环的入口即可,返回入口结点即可。
比如:
返回 3
这个结点即可。
方法一:hashMap
我们从头开始遍历这个链表,如果某一个节点在 map 中已经存在了,就意味着这个结点是环的入口。
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
// write code here
if(pHead === null) return null
const map = new Map()
let cur = pHead
while(cur) {
if(map.has(cur)) {
return cur
}
// 表示这个节点被存入
map.set(cur, true)
cur = cur.next
}
// 没有结果,我们返回 null
return null
}
module.exports = {
EntryNodeOfLoop : EntryNodeOfLoop
};
方法二:只要有环,一定相遇
需要理解的是:只要有环,快慢指针在一定时间后一定会相遇。并且这个时候如果将慢指针移动到开头,然后快慢指针同时移动,最终就会在循环节点处相遇。
比如下图:慢指针每次移动一个,快指针每次移动两个,只要有环,最终会在某一个节点相遇,这里是2。
具体为什么会有这个现象出现,就是快慢指针最终会在环的入口相遇这个现象,请看这个文章的解释:
https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#%E6%80%9D%E8%B7%AF
具体代码:
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
if(pHead === null) return null
let fast = pHead
let slow = pHead
// 这里这种写法就可以判断出这个链表中是否又环了,实在无法理解可以记住,也不长
while(fast !== null && fast.next !== null) {
slow = slow.next
fast = fast.next.next
if(slow === fast) {
break
}
}
if(fast === null || fast.next === null) {
return null
}
// 开始找环的位置
slow = pHead
while(slow !== fast) {
slow = slow.next
fast = fast.next
}
return slow // 或者 return fast 也行
}
module.exports = {
EntryNodeOfLoop : EntryNodeOfLoop
};