leetcode-链表-环形链表2

题干

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

要求

空间复杂度O(1)

流程分析

这个题需要使用快慢指针,即可转换为追赶问题。追赶问题就会存在等式:

快的速度 = k慢的速度

我们假设快指针是满指针速度的两倍,则有:

快路程/t = 2慢路程/t,即:快路程=慢路程2 (1)

下面我们只要分别求出快路程和慢路程即可。
我们设该链表起始节点为A,入环的第一个节点为B,快慢指针第一次相遇的位置为C。
设A到B的距离为a,B到C的距离为b,C到B的距离为c。假设快慢指针第一次相遇时,快指针走了n圈环,满指针走了m圈环,则有:

快路程=n(b+c)+a+b
慢路程=m(b+c)+a+b

根据公式(1)我们有:

n(b+c)+a+b = 2m(b+c)+2a+2b
即:a=(n-2m)(b+c)-b
即: a=(n-2m-1)(b+c)+c

所以当快慢指针第一次相遇时,只需要再新建一个指针从头走到与慢指针相遇即可得到入环的第一个节点。

代码

public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null){
return null;
}
ListNode slow = head;
ListNode fast = head;
while (slow != null && fast != null){
slow = slow.next;
if (fast != null && fast.next != null){
fast = fast.next.next;
}else{
break;
}
if (slow == fast){
ListNode newNode = head;
while (newNode != fast){
newNode = newNode.next;
fast = fast.next;
}
return newNode;
}
}
return null;
}
}

posted @ 2023-02-12 17:05  盲从者列表  阅读(39)  评论(0)    收藏  举报