标签:
设计两个指针变量p和q,都指向链表表头,遍历该链表,且p=2p,当遍历到p=q时,说明该链表存在环路,如果p为null,则说明该链表不存在环路。
boolean isLoop(Link head){ Link p = head; Link q = head; while(p != null){ p = p.next; if(p == null) break; p = p.next; q = q.next; if(p == q){ System.out.println("there is a loop in the link"); break; } } if(p == null){ System.out.println("there is no loop in the link"); return false; } return true; }
结论:分别从p和q相遇的结点和头结点依次向后遍历,当遍历指针再次相遇时,相遇节点即为起始节点。
推导过程:如下图所示红色结点为相遇结点,头结点到起始节点的距离为m,起始节点到相遇结点的距离为n,环为r,链表的长度为L。
当经过m+n步之后p和q相遇,即m+n=kr=(k-1)r+r=(k-1)r+L-m,即可得:m=(k-1)r+L-m-n。从而得出头结点到环起始节点的距离等于相遇结点到起始节点的距离。
Link firstNode(Link head){ Link fast = head; Link slow = head; while(fast != null && fast.next != null){ fast = fast.next.next; slow = slow.next; if(fast == slow) break; } if(fast == null) return null; //there is no loop in the linkList fast = head; while(fast != slow){ fast = fast.next; slow = slow.next; } return fast; }
按照如上所得的起始节点,一次遍历直到再次遍历到起始节点,则可得环的长度;如只计算环的长度,则从slow和fast相遇结点开始计数,直到再次到达相遇结点,slow所走过的长度即为环的长度。
int loopLength(Link head){ Link slow = head; Link fast = head; int length = 0; boolean Flag = false; //是否相遇过一次 while(fast != null && fast.next != null){ fast = fast.next.next; slow = slow.next; if(Flag) length++; if(fast == slow){ if(Flag == false) Flag = true; else{ break; } } } return length; }
将其中的一个链表首尾相连,然后判断另一个链表是否带环即可,如下图所示:
标签:
原文地址:http://www.cnblogs.com/zhanglei93/p/5815305.html