单向链表中关于环的问题
首先我们来看一张图片(转):
如图所示:链表的起点为X,环的起点为Y,相遇点为Z,则环的长度为L=b+c。
利用快慢指针,一个fast每次走两步,另一个slow走一步,如果有环两者就会相遇;因此,两者第一次相遇时有关系成立:2*(a+b)=a+b+c+b,则a=c;
(1)判断当前链表中是否存在环?(Linked List Cycle I)
判断fast是否有等于slow的情况。
/*
* 判断单链表中是否存在环!
* 利用快慢指针,一个每次走两步,另一个走一步,如果有环两者就会相遇;
*/
static public boolean hasCycle(ListNode head) {
boolean flag=false;
ListNode fast=head;
ListNode slow=head;
while(true){
if(fast==null||fast.next==null)
return false;
slow=slow.next;
fast=fast.next.next;
if(fast==slow){
flag=true;
break;
}
}
return flag;
}
(2)判断当前链表中环的长度?
环的长度L=a+b;即第一次相遇时,slow走的长度。
(3)判断当前链表中环的起点?(Linked List Cycle II)
当两者相遇时,fast从X走,slow从Z走,每次走一步,再次相遇点就是环的起始点。
<span style="font-size:18px;">/*
* 判断单链表中是否存在环,返回环的起点!
* 利用快慢指针,一个每次走两步,另一个走一步,如果有环两者就会相遇;
* 一个从头开始走,一个在相遇点走,两者再次相遇的地方就是环的起点。
*/
static public ListNode detectCycle(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(true){
if(fast==null||fast.next==null)
return null;
slow=slow.next;
fast=fast.next.next;
if(fast==slow){
break;
}
}
fast=head;
while(fast!=slow){
fast=fast.next;
slow=slow.next;
}
return fast;
}</span>
(4)如何将当前链表中的环消除?
将环中指向Y的结点的next该为null。
(5)判断两个链表是否存在交点?
1)先判断两个链表中是否有环,如果一个没有,另一个有,则肯定不相交;2)如果两者都没有环,则判断两个链表的尾部结点是否相同;3)两者都有环,找到环的起点,从环的起点遍历两者是否有公共点。