嗨!~ 大家好,我是YK菌 🐷 ,一个微系前端 ✨,喜欢分享自己学到的小知识 🏹,欢迎关注我呀 😘 ~ [微信号:
yk2012yk2012
,微信公众号:ykyk2012
]
「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
昨天我们刷了一道环形链表,今天我们来一道环形链表II
142. 环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回
null
。
为了表示给定链表中的环,我们使用整数
pos
来表示链表尾连接到链表中的位置(索引从0
开始)。 如果pos
是-1
,则在该链表中没有环。注意,pos
仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/li…
【解法一】使用Map
和上一题一样,直接使用 Map
的解法,保存遍历过的结点,遇到第一个遍历过的就返回它
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
};
虽然可以解决问题,但是效率还是太低了
【解法二】快慢指针
我们使用第二种方法,快慢指针的方法,但是这题困难就困难在不是判断有没有环,而是找到环中第一个结点。
这里我们需要画图说明一下了
假设慢指针走了x
个结点与快指针相遇,因为快指针速度是慢指针的两倍,所以快指针走过了2x
个结点
快慢指针相遇的结点不一定是环的起点,但是由此可知环中有x
个结点
我们假设环的起点,到两个指针相遇点距离 k
个结点。此时我们可以计算出从头到起点的距离为 x - k
, 而从相遇点遍历到起点也是 x - k
。
此时,我们再用一个指针从头开始遍历,一次一步。慢指针继续一步一步遍历。它们会在走过x-k
个结点的地方相遇,而相遇的地方就是环的起点。
var detectCycle = function(head) {
if(head === null) return null
let slow = head
let fast = head
while(fast){
if(fast.next===null) return null
slow = slow.next
fast = fast.next.next
// 快慢指针相遇
if(slow === fast){
let pre = head
while(slow !== pre){
pre = pre.next
slow = slow.next
}
return pre
}
}
return null
};
最后,欢迎关注我的专栏,和YK菌做好朋友~