问题描述:java
有一个单链表,其中可能有一个环,也就是某个节点的next指向的是链表中在它以前的节点,这样在链表的尾部造成一环。 oop
如何判断一个链表是否是这类链表? spa
问题扩展: 指针
若是链表可能有环呢?code
若是须要求出两个链表相交的第一个节点呢? orm
问题分析:
it
在无环的状况下,若是两个链表有结点相同,那么它们下一结点也相同,如此可推出尾结点也相同。 ast
那么只要判断两链表的尾结点是否相同。(O(len1+len2))class
//if there is no cycle boolean isJoinedSimple(Node n1, Node n2){ while(n1 != null) n1 = n1.next; while(n2 != null) n2 = n2.next; return n1 == n2; }
扩展1:扩展
须要先判断有环无环,能够这样作,定义两个指针,指向头结点,一个每次移动一个结点,另外一个每次移动两个结点,若是慢的能追上快的(也就是两个指针重逢),就说明有环。
boolean hasLoop(Node n){ Node nFast = n; Node nSlow = n; while(nFast != null && nSlow != null){ nFast = nFast.next.next; nSlow = nSlow.next; if(nFast == nSlow) return true; } return false; }
利用以下方法分别找到两个链表的环入口。首先设置一个快慢指针p_fast和p_slow,找到两个指针相交的点,p_inter。而后p从链表开头,p_slow从p_inter开始走,每次都走1步,则两个指针相交的地方,就是链表的入口。
(a) 分别求得A和B两个链表的入口,若是同样。则两个链表相交的第一个节点方法同1,只是将环当成NULL便可。
(b) 若是两个链表的环入口不同,则没有第一个相交节点。
扩展2:
如何找到入口点:
当fast若与slow相遇时,slow确定没有走遍历完链表,而fast已经在环内循环了n圈(1<=n)。假设slow走了s步,则fast走了2s步(fast步数还等于s 加上在环上多转的n圈),设环长为r,则:
2s = s + nr
s= nr
设整个链表长L,入口环与相遇点距离为x,起点到环入口点的距离为a。
a + x = nr
a + x = (n – 1)r +r = (n-1)r + L - a
a = (n-1)r + (L – a – x)
(L – a – x)为相遇点到环入口点的距离,由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点,因而咱们从链表头、与相遇点分别设一个指针,每次各走一步,两个指针一定相遇,且相遇第一点为环入口点。程序描述以下:
Node findLoopPort(LinkedList lst){ Node nFast = lst.head; Node nSlow = lst.head; while(nFast != null && nFast.next!= null){ nFast = nFast.next.next; nSlow = nSlow.next; if(nFast == nSlow) break; } if(nFast == null || nSlow == null) return null; nSlow = head; while(nSlow != nFast){ nSlow = nSlow.next; nFast = nFast.next; } return nSlow; }