問題描述:
乙個比較經典的問題,判斷兩個鍊錶是否相交,如果相交找出他們的交點。
思路:1、碰到這個問題,第一印象是採用hash來判斷,將兩個鍊錶的節點進行hash,然後判斷出節點,這種想法當然是可以的。
2、當然採用暴力的方法也是可以的,遍歷兩個鍊錶,在遍歷的過程中進行比較,看節點是否相同。
3、第三種思路是比較奇特的,在程式設計之美上看到的。先遍歷第乙個鍊錶到他的尾部,然後將尾部的next指標指向第二個鍊錶(尾部指標的next本來指向的是null)。這樣兩個鍊錶就合成了乙個鍊錶,判斷原來的兩個鍊錶是否相交也就轉變成了判斷新的鍊錶是否有環的問題了:即判斷單鏈表是否有環?
這樣進行轉換後就可以從鍊錶頭部進行判斷了,其實並不用。通過簡單的了解我們就很容易知道,如果新煉表是有環的,那麼原來第二個鍊錶的頭部一定在環上。因此我們就可以從第二個鍊錶的頭部進行遍歷的,從而減少了時間複雜度(減少的時間複雜度是第乙個鍊錶的長度)。
下圖是乙個簡單的演示:
這種方法可以判斷兩個鍊錶是否相交,但不太容易找出他們的交點。
4、仔細研究兩個鍊錶,如果他們相交的話,那麼他們最後的乙個節點一定是相同的,否則是不相交的。因此判斷兩個鍊錶是否相交就很簡單了,分別遍歷到兩個鍊錶的尾部,然後判斷他們是否相同,如果相同,則相交;否則不相交。示意圖如下:
判斷出兩個鍊錶相交後就是判斷他們的交點了。假設第乙個鍊錶長度為len1,第二個問len2,然後找出長度較長的,讓長度較長的鍊錶指標向後移動|len1 - len2| (len1-len2的絕對值),然後在開始遍歷兩個鍊錶,判斷節點是否相同即可。
下面給出乙個簡單的實現:
typedef struct node_t
int data;//data}node;struct node_t *next; //next
node* find_node(node *head1, node *head2)
if(null == head1 || null == head2)通過上面的操作就可以找到兩個鍊錶的交點了。return null;//如果有為空的鍊錶,肯定是不相交的
node *p1, *p2;
p1 = head1;
p2 = head2;
int len1 = 0;
int len2 =0;
int diff = 0;
while(null != p1->next)
p1 = p1->next;
len1++;
while(null != p2->next)
p2 = p2->next;
len2++;
if(p1 != p2) //如果最後乙個節點不相同,返回null
return null;
diff = abs(len1 - len2);
if(len1 > len2)
p1 = head1;
p2 = head2;
else
p1 = head2;
p2 = head1;
for(int i=0; ip1 = p1->next;
while(p1 != p2)
p1 = p1->next;
p2 = p2->next;
return p1;
5、總結
上面的幾種方法中最後一種是比較不錯的,當然hash也是可以的。
問題的延伸:
如果原來的兩個鍊錶中有環怎麼處理?
檢查兩個單鏈表是否有交點
思路1 先遍歷第乙個鍊錶到他的尾部,然後將尾部的next指標指向第二個鍊錶 尾部指標的next本來指向的是null 這樣兩個鍊錶就合成了乙個鍊錶,判斷原來的兩個鍊錶是否相交也就轉變成了判斷新的鍊錶是否有環的問題了 即判斷單鏈表是否有環?思路2 如果他們相交的話,那麼他們最後的乙個節點一定是相同的,否...
判斷兩個單鏈表是否相交
首先要搞清楚單鏈表相交的概念和特點 指的是他們存在完全重合的部分,不是交叉到乙個點 不存在這種情況,可以想想為什麼 判斷其是否相交的方法有以下幾種。1 最傳統方法 雙重迴圈,依次查詢,是否有位址相同的節點,時間複雜度o list1.len list2.len 空間複雜度o 1 2 hash法 先遍歷...
判斷兩個單鏈表是否相交
方法一 直接法 直接判斷第乙個鍊錶的每個結點是否在第二個鍊錶中,時間複雜度為o len1 len2 耗時很大 方法二 利用計數 如 果 兩個鍊錶相交,則兩個鍊錶就會有共同的結點 而結點位址又是結點唯一標識。因而判斷兩個鍊錶中是否存在位址一致的節點,就可以知道是否相交了。可以對第一 個鍊錶的節點位址進...