判斷兩條鍊錶是否相交 單鏈表是否有環

2021-06-26 01:20:28 字數 2814 閱讀 7562

相交的話,一定是y型或者v型的。所以只需要判斷兩個鍊錶最後乙個節點就可以了。

問題描述:

給定兩個單向列表的頭指標,比如h1、h2,判斷這兩個列表是否相關。

注,這裡只討論這兩個列表均不帶環的情況。

解法一:直觀的想法

估計有些人一看到這個題目,便不管三七二十一,從第乙個鍊錶開始遍歷,判斷它的每乙個節點是否在第二個鍊錶中。這是最簡單的方法,但是時間複雜度卻是o(length(h1)*length(h2)),非常耗時間。

解法二:

由於兩個列表都沒有環,那麼我們可以把第二條鍊錶接到第一條鍊錶後面,如果得到的鍊錶有環,則說明這兩條鍊錶有相交,如果沒有環,則說明這兩條鍊錶沒相交。判斷乙個鍊錶是否有環,也不是一件簡單的事,但是這裡我們可以發現,假如有環,則第二條鍊錶的表頭一定在環上,因此我們只需要從第二條鍊錶開始遍歷,看是否會回到起始點就可以判斷出來,當然了,最後不要忘了恢復原來的狀態,去掉第乙個鍊錶到第二個煉表表頭的指向。

解法三:

上面的解法二的解法比起解法一來說明顯高效了很多,但是要把兩條鍊錶拼起來,最後還要恢復它的狀態,不免太麻煩了一點,那麼有沒有更好的辦法呢?我們知道假如兩條鍊錶相交於某節點上,那麼從該節點開始,兩條鍊錶共用同乙個結點,也就是說最後乙個節點肯定是共用的,這樣我們便可以通過判斷最後乙個結點是否為兩條鍊錶共用來判斷兩條鍊錶是否相交。

首先先遍歷第一條鍊錶,記住最後乙個節點,接著遍歷第二條鍊錶,到最後乙個節點時與第一條鍊錶的最後乙個節點相比較,如果兩個節點相同,則兩條鍊錶相交,否則為不相交。該演算法的時間複雜度為o(length(h1)+length(h2)),而且只用了乙個額外的指標來儲存最後乙個節點,無疑地,這個方法比解法二更優。

擴充套件問題 如果兩個鍊錶相交,找出相交的第乙個節點?

在判斷相交的過程中要分別遍歷兩個鍊錶,同時記下各自的長度。然後再遍歷一次:長鍊表節點先從頭節點出發前進(lengthmax-lenghmin)步,之後兩個鍊錶同時前進,每次一步,相遇的第乙個節點即為兩個鍊錶相交的第乙個節點。程式描述如下:

node *intersection(node *head1, node *head2)

if(!head1 || !head2)

return null;

int len1 = 1;

int len2 = 1;

bool result = false;

//判斷兩個鍊錶是否相交,同時記下各個鍊錶的長度

node *p = head1;

while(p->next)

plen++; p=p->next

q=head2

while(q->next)

len2++; q=q->next

result=(p==q)

if(result)

int steps = abs(len1 – len2)

node *head = len1 > len2 ? head1 : head2;

while(steps)

head = head->next

steps –-

len1 > len2 ? p = head,q=head2 ? q = head,p=head1

while(p!=q)

p=p->next

q=q->next

return p

return null

二、鍊錶中含有環

鍊錶中有環如下圖:

1.鍊錶中是否有環的判斷

可以設定兩個指標(fast,slow),初始值均指向頭,slow每次向前一步,fast每次向前兩步;

如果鍊錶中有環,則fast先進入環中,而slow後進入環中,兩個指標在環中必定相遇;

如果fast遍歷到尾部為null,則無環

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)迴圈內環+相遇點到環入口點

因而,可以在煉表頭,相遇點分別設定乙個指標,每次各走一步,兩個指標必定相遇,則相遇第一點為環入口點

linklist *  listloop(linklist *list) //判斷乙個鍊錶中是否有環

} if(isloop==1)//鍊錶中有環時

return slow; }

else 

}  當兩個鍊錶中有環時,相交的判斷:

(1)首先分別找出兩個鍊錶入環的第乙個結點記為p1,p2

(2)如果p1==p2,說明兩個鍊錶在入環之前或入環的第乙個結點相交;則此

時可以轉為兩個鍊錶均不帶環相交的判斷,把p1,p2當作最後的末尾結點

(3)如果p1!=p2,此時兩個鍊錶可能完全不相交;也可能兩個鍊錶完全共有同乙個環。

此時,判斷

p1->next與p2->next是否相等,如果相等則兩鍊錶完全共環;如果不相等,則完全不相交。

當乙個鍊錶中有環,乙個鍊錶中沒有環時,兩個鍊錶必不相交。

from: 

判斷兩條鍊錶是否相交 單鏈表是否有環

相交的話,一定是y型或者v型的。所以只需要判斷兩個鍊錶最後乙個節點就可以了。問題描述 給定兩個單向列表的頭指標,比如h1 h2,判斷這兩個列表是否相關。注,這裡只討論這兩個列表均不帶環的情況。解法一 直觀的想法 估計有些人一看到這個題目,便不管三七二十一,從第乙個鍊錶開始遍歷,判斷它的每乙個節點是否...

判斷單鏈表是否存在環 判斷兩鍊錶是否相交

給定乙個單鏈表,只給出頭指標h 1 如何判斷是否存在環?2 如何知道環的長度?3 如何找出環的連線點在 4 帶環鍊錶的長度是多少?解法 1 對於問題1,使用追趕的方法,設定兩個指標slow fast,從頭指標開始,每次分別前進1步 2步。如存在環,則兩者相遇 如不存在環,fast遇到null退出。2...

判斷兩條線段是否相交

如上圖,判斷線段ab和線段cd相交。分析 如果線段ab和線段cd相交,只能是圖中的兩種相交情況。可以用向量叉乘來判斷。如果 向量ab叉乘向量ac 向量ab叉乘向量ad 0 並且 向量cd叉乘向量ca 向量cd叉乘向量cb 0,那麼說明線段ab與線段cd相交。設a x1,y1 b x2,y2 c x3...