题目:
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
进阶:
你是否可以使用 O(1) 空间解决此题?
思路:
- 先具备141的理论基础
- 1、设置快慢指针,假如有环,他们最后一定相遇。
- 2、两个指针分别从链表头和相遇点继续出发,每次走一步,最后一定相遇与环入口。
两个结论的证明:
空口无凭,如何证明上面两个结论呢
1、设置快慢指针,假如有环,他们最后一定相遇。
2、两个指针分别从链表头和相遇点继续出发,每次走一步,最后一定相遇与环入口。
证明结论1:设置快慢指针fast和low,fast每次走两步,low每次走一步。假如有环,两者一定会相遇(因为low一旦进环,可看作fast在后面追赶low的过程,每次两者都接近一步,最后一定能追上)。
证明结论2:
设:
链表头到环入口长度为--a
环入口到相遇点长度为--b
相遇点到环入口长度为--c

则:相遇时
快指针路程=a+(b+c)k+b ,k>=1 其中b+c为环的长度,k为绕环的圈数(k>=1,即最少一圈,不能是0圈,不然和慢指针走的一样长,矛盾)。
慢指针路程=a+b
快指针走的路程是慢指针的两倍,所以:
(a+b)*2=a+(b+c)k+b
化简可得:
a=(k-1)(b+c)+c 这个式子的意思是: 链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈环长度。其中k>=1,所以k-1>=0圈。所以两个指针分别从链表头和相遇点出发,最后一定相遇于环入口。
代码:
public ListNode detectCycle(ListNode head) {
ListNode meetNode=null;
if (head==null){
return null;
}
//一个一次走两步的 一个一次走一步的,如果两人能两次相遇(起点,终点),必然存在环
ListNode fast=head;
ListNode slow=head;
int meetCount=0;
while (slow!=null){
if (fast==slow){
meetCount++;
}
if (meetCount==2){
meetNode=slow;
break;
}
//如果过程中快指针出现了null说明没环
if (fast==null||fast.next==null){
return null;
}
fast=fast.next.next;
slow=slow.next;
}
fast=head;
while (fast!=meetNode){
fast=fast.next;
meetNode=meetNode.next;
}
return fast;
}

网友评论