Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一.题目
剑指 Offer II 022. 链表中环的入口节点 给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着
next指针进入环的第一个节点为环的入口节点。如果链表无环,则返回null。
为了表示给定链表中的环,我们使用整数 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, 104]内 -105 <= Node.val <= 105pos的值为-1或者链表中的一个有效索引
二、思路分析:
这道题目很经典,判断链表中环的入口,首先一般链表的相关操作都是逃不过双指针的,那么这道题我们如何双指针求解问题?已经链表中有环,我们就利用快慢指针来解决问题。
首先我们把两个指针都初始化指向头结点,然后让快指针fast每一步移动两个结点,慢指针slow移动一个结点,如果链表中存在环的话,那么两个指针肯定能够相遇。因为fast再相遇的时候走了2K步,而slow走了K步,那么K一定是环长度的整数倍,此时如果相遇点距离环入口点长度为m,那么我们将慢指针重新指向头结点,然后到达环入口结点只需要K-m步,随后让快指针跟慢指针同步的走,那么快指针正好与慢指针在环入口相遇。
三、代码:
/**
* 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 == null || head.next == null) return null
//快慢指针
let slow = fast = head
while(fast !== null &&fast.next !== null){
fast = fast.next.next
slow = slow.next
if(fast == slow) break
}
//判断是否成环
if(fast == null || fast.next == null) return null
//慢指针重新指向头结点
slow = head
while(fast !== slow){
fast = fast.next
slow = slow.next
}
return slow
};
四、总结:
首先这道题的思路依然是双指针发挥作用,链表中有环那么快慢指针肯定能够相遇。需要注意的是我们需要判断链表是否有环需要在第一次相遇后判断快指针以及快指针的下一个结点是否为空,不然当两个指针都置空的时候条件也是成立的但是不符合题目。