IT公司100題-7-判斷兩個鏈表是否相交

問題描述:java

有一個單鏈表,其中可能有一個環,也就是某個節點的next指向的是鏈表中在它以前的節點,這樣在鏈表的尾部造成一環。 oop

  1. 如何判斷一個鏈表是否是這類鏈表? spa

問題擴展: 指針

  1. 若是鏈表可能有環呢?code

  2. 若是須要求出兩個鏈表相交的第一個節點呢? 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;
}
相關文章
相關標籤/搜索