「这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战」。
题目
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例1
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
示例2
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
思路
这道题是在上一篇文章的基础 LeetCode 👉 HOT 100 👉 环形链表 - 简单题 ,除了要判断链表中是否存在环,还要求入环的第一个节点,例1即为节点 2
;
如果链表中存在环,在遍历链表时,遇到的第一个重复元素,即为入环节点;可以按照上一篇文章的思路,使用 Set
结构存储已访问的节点,返回第一个重复的节点即可
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var detectCycle = function(head) {
const set = new Set();
while (head) {
// 返回重复的第一个节点
if(set.has(head)) {
return head;
} else {
set.add(head);
head = head.next;
}
}
return null;
};
上面的解法,问题还是在空间复杂度太高,为 O(n)
; LeetCode
官网解法,使用了 slow, fast, ptr
三个指针,利用数学公示推导,也可以得到入环的节点,感兴趣的可以自己看看,传送门 ☞
这里提供另一种思路,假如链表中存在环,同时求得环的长度 len
,那么对于倒数第 len
个节点,不就是入环节点么~
具体步骤如下:
-
使用
slow、fast
两个指针,判断环是否存在;当环存在,在两个指针相遇时,保存相遇的节点为meetNode
,此时该结点一定在环内;环不存在则直接返回 null -
初始化
len = 0
,让meetNode
继续在环内遍历,每次遍历都进行len++
,结束条件为meetNode == fast
,此时len
即为环的长度; -
再次使用
slow、fast
两个指针,初始化为头节点head
,让fast
指针先走len
步;再让两指针同时走,当fast.next == slow
的时候,说明fast
到达了尾节点,此时slow
指针即指向入环节点。
/**
* @param {ListNode} head
* @return {ListNode}
*/
var detectCycle = function(head) {
if(!head) return null;
// 判断是否有环
let slow = head, fast = head.next;
while (slow != fast) {
if(!fast || !fast.next) {
return null;
}
slow = slow.next;
fast = fast.next.next;
}
// 计算环的长度
let len = 0, meetNode = fast;
while(meetNode.next != fast) {
meetNode = meetNode.next;
len++;
}
// 重新初始化 快慢指针
slow = head, fast = head;
// 快指针先走
while(len > 0) {
fast = fast.next;
len--;
}
// 当fast到达尾节点,尾节点的 next 会与 slow相等
while(slow = !fast.next) {
slow = slow.next;
fast = fast.next;
}
// 当前的slow即为入环节点
return slow;
};
小结
如果实在没思路,就画图,往往规律就在画图的过程中,会暴漏出来。
对于链表的操作,双指针,往往能派上用场~
LeetCode 👉 HOT 100 👉 环形链表 II - 中等题 ✅
合集:LeetCode 👉 HOT 100,有空就会更新,大家多多支持,点个赞👍
如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄