判斷倆個鏈表是否相交node
給出倆個單向鏈表的頭指針,好比 h1,h2,判斷這倆個鏈表是否相交。spa
爲了簡化問題,咱們假設倆個鏈表均不帶環。指針
問題擴展:code
若是須要求出倆個鏈表相交的第一個節點列ast
鏈表定義class
typedef struct node { int data; struct node * next; }List;
若是不帶環,那麼分別遍歷兩個鏈表到尾節點。
擴展
若果兩個鏈表相交,那麼尾節點必定相交List
若是兩個鏈表不相交,那麼尾節點必定不相交;循環
int isJoinedNocylic(List * h1,List * h2) { while(h1 != NULL) h1 = h1->next; while(h2 != NULL) h2 = h2->next; return h1 == h2; }
若是須要求出倆個鏈表相交的第一個節點列?遍歷
網上看到了這樣的一個解法:設置兩個指針fast和slow,初始值都指向頭,slow每次前進一步,fast每次前進二步,若是鏈表存在環,則fast一定先進入環,而slow後進入環,兩個指針一定相遇。(固然,fast先行頭到尾部爲NULL,則爲無環鏈表),這樣就能夠判斷兩個鏈表是否相交了,程序以下:
int isCycle(List * h) { List * p1, * p2; p1 = p2 = h; int flag; while(p2 != NULL && p2->next != NULL) { p1 = p1->next; p2 = p2->next->next; if(p1 == p2) { flag = 1; break; } } flag = 0; return flag; }
下面看看怎麼找環的入口,當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)循環內環+相遇點到環入口點(從相遇點向後遍歷循環回到入口點的距離),因而咱們從鏈表頭、與相遇點分別設一個指針,每次各走一步,兩個指針一定相遇,且相遇點爲環入口點,也即爲兩個鏈表的第一個相同節點。程序描述以下:
List * isJoined(List * h1,List * h2) { List * ph1,*p1,*p2; int flag; ph1 = h1; while(ph1->next != NULL) ph1 = ph1->next; ph1->next = h2; if(0 == isCycle(h1)) { flag = 0; } else { p1 = h1; while(p1 != p2) { p1 = p1->next; p2 = p2->next; } flag = p1; } return flag; }