给定一个单链表,只给出头指针h:
1、 如何判断是否存在环?
证明:
slow首次在A点进入环路时,fast一定在环中的B点某处。设此时slow距head长为x,B点距A点长度为y,环周长为s。因为fast和slow的步差为1,所以slow前行距离为y的时候,恰好会被fast在M点追上。因为y<s,所以slow尚未完成一次遍历。
//判断单链表是否有环
public static boolean hasCycle(ListNode head) {
if(head == null || head.next == null){
return false;
}
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
return true;
}
}
return false;
}
2、 如何知道环的长度?
证明:(有公式所以截图了)
//返回环的长度
public static int cycleLength(ListNode head) {
if(head == null || head.next == null){
return 0;
}
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
fast = fast.next.next;
int length = 2;
while(fast != slow){
fast = fast.next.next;
length = length + 2;
}
return length;
}
}
return 0;
}
3、 如何找出环的连接点在哪里?
证明:在fast和slow第一次相遇的时候,假定slow走了n步骤,环路的入口是在x步的时候经过的,那么有
slow走的路径: x+y = n; y为fast和slow相交点M距离环路入口的距离
fast走的路径: x+y+k*s = 2*n; s为环路的周长,k是整数
所以得出 n = k*s;
显然,如果从x+y点开始,slow再走n步的话,还可以回到x+y这个点(绕了k圈)
同时另一个指针temp从头开始走的话,经过n步,也会达到x+y这点
两者都减去y步,可知两者走x步必然会在环路的入口点处相遇
//找出环的起始点在哪里
public static ListNode getCycleStartNode(ListNode head) {
if(head == null || head.next == null){
return null;
}
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
fast = head;
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
return null;
}
4、带环链表的长度是多少?
证明:总长度 = s + x;
//带环链表总长度,0表示没环
public static int getListLength(ListNode head) {
if(head == null || head.next == null){
return 0;
}
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
ListNode p = slow;//标记相遇的地方
fast = head;
int lengthX = 0;
int lengthS = 0;
while(fast != slow){
fast = fast.next;
slow = slow.next;
lengthX++;
}
lengthS = lengthX;
while(slow != p){
slow = slow.next;
lengthS++;
}
return lengthX+lengthS;
}
}
return 0;
}