给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
思路:
设定一个fast一次走两步,slow一次走一步,当fast=slow时,此时证明单链表中有环,把slow输出即可。
小思考:
本题给出的思路是fast是slow的二倍,那么请思考一下,fast可不可以是slow的三倍?四倍?甚至更多倍呢?
答案肯定是可以的呢,只不过是运算时间的不同而已。但是事实证明,当fast是slow的二倍的时候走的是最少的,即运算时间是最短的。
如下图:如果链表中有环,fast和slow相遇,fast走的路程是slow的2倍,从链表开头到环的入口点长度为X,从入口点到相遇点长度为y,设整个环的长度为C
则可列出关系等式如下:
2(x+y) == x + NC + y
拆开后:x+y = NC
x = NC - y
因为一个链表的x和y是一定的,所以NC是一个定值。
如果N为1,则环的下半部分为即x。
Java代码(快慢指针法)
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast .next != null) {
fast = fast.next.next;
slow = slow.next;
if(slow == fast) {
break;
}
}
if(fast == null || fast.next == null) {
return null;
}
slow = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
Java代码(快慢指针法)
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast){
while(slow != head){
slow = slow.next;
head = head.next;
}
return slow;
}
}
return null;
}
}
Java代码(哈希表法)
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode pos = head;
Set<ListNode> visited = new HashSet<ListNode>();
while (pos != null) {
if (visited.contains(pos)) {
return pos;
} else {
visited.add(pos);
}
pos = pos.next;
}
return null;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/linked-list-cycle-ii/solutions/441131/huan-xing-lian-biao-ii-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。