【剑指算法NO.02】142.环形链表II
共 1725字,需浏览 4分钟
·
2021-11-24 10:24
本篇是在141.环形链表的基础上进行的分析和运算。没有看之前文章的推荐先看上篇再看本篇。
入环口判断
上篇开头我们提到过,需要利用快慢指针在环中的移动规律来得到环的入口点。
现在我们紧接着上篇的思路,再来探讨一下,怎么根据快慢指针找出入环口结点。
按照之前的推论,当快慢指针在相遇点汇合时,相遇点距离入环口的距离就是L-(L-A)
,也就是距离为A
,
冥冥中注定,我们可以从图中看到,链表起点(head 头节点)到达入环口的距离也是A
现在我们让慢指针站住不动、快指针回到头节点。之后再让 快、慢指针同时开始运动、且保持步数都为1。快指针以一次 1 步的速度,从头节点
向入环口
运动;慢指针也以一次 1 步的速度,从相遇点
向入环口
运动;因为快、慢指针的距离相同,所以二者会在入环口再次相遇:在他们相遇时,我们就能得到入环口对应的结点是谁了。
上代码
我们第一遍循环的时候,先找到相遇点。并在第一次的相遇点处让快指针回到开头、并把速度降低到和慢指针一样。接下来第二遍循环,我们只需要找到二者相等的位置结点并返回即可。
/**
* 快慢指针
*/
var detectCycle = function(head) {
// 先判断是否具备形成环的条件(结点数量不能小于两个)
if(head === null || head.next === null) return null
// 准备好快慢指针
let slow = head
let fast = head
// 第一遍循环,找相遇点
while(fast && fast.next) {
// 快指针一次走2步,慢指针一次走1步
slow = slow.next
fast = fast.next.next
// 相遇以后结束循环,并让快指针回到起始节点
if(slow === fast) {
// 在相遇点相遇了,就要fast赶回起点
fast = head
break
}
}
// 没相遇且结束了循环,就说明没有环,直接return null
if(fast !== head) return null
// 否则说明有环,第二次遍历寻找入环口
while(slow !== fast) {
// fast和slow分别从起点及相遇点出发,每次走1步,直到相遇就是入环口。
slow = slow.next
fast = fast.next
}
// 最后返回入环口的结点(因为此时slow===fast,所以返回谁也行)
return slow
};
对比哈希的缺点:如果链表长、环的长度比非环的长度小,则需要更多次的循环
同样的,这个题依旧可以使用哈希表的方式来求解:
/**
* 哈希表
* 缺点:空间复杂度。哈希就是空间换时间
*/
var detectCycle = function(head) {
let map = new Map()
while(head) {
if(map.has(head)) return head
map.set(head, true)
head = head.next
}
return null
};
Hi,读到这里的你~
我们有一群人(十来个吧)正在组队用JS刷 LeetCode 算法题,小队内有明确的打卡规则与惩罚制度,队员们也都每天积极的刷题打卡。如果你也想加入的话请与我联系,欢迎进来和我们一起成长。
刷题排行榜:http://123.56.222.177/
算法打卡地址:https://gitee.com/xingorg1/algorithmic-clock-out/issues
让我们一起携手同走前端路!
长按下图识别二维码 关注公众号回复【加群】即可