判斷兩個鍊錶是否相交,若相交,求交點。

2021-07-22 04:19:31 字數 3608 閱讀 4237

第一種情況:兩個鍊錶均不含有環

思路:

1、直接法

採用暴力的方法,遍歷兩個鍊錶,判斷第乙個鍊錶的每個結點是否在第二個鍊錶中,時間複雜度為o(len1*len2),耗時很大。

2、hash計數法

以鍊錶節點位址為值,遍歷第乙個鍊錶,使用

hash

儲存所有節點位址值,結束條件為到最後乙個節點(無環)或

hash

中該位址值已經存在(有環)。

再遍歷第二個鍊錶,判斷節點位址值是否已經存在於上面建立的

hash

表中。這個方面可以解決題目中的所有情況,時間複雜度為

o(m+n),m

和n分別是兩個鍊錶中節點數量。由於節點位址指標就是乙個整型,假設鍊錶都是在堆中動態建立的,可以使用堆的起始位址作為偏移量,以位址減去這個偏移量作為

hash

函式3、先遍歷第乙個鍊錶到他的尾部,然後將尾部的next指標指向第二個鍊錶(尾部指標的next本來指向的是null)。這樣兩個鍊錶就合成了乙個鍊錶,判斷原來的兩個鍊錶是否相交也就轉變成了判斷新的鍊錶是否有環的問題了:即判斷單鏈表是否有環?

這樣進行轉換後就可以從鍊錶頭部進行判斷了,其實並不用。通過簡單的了解我們就很容易知道,如果新煉表是有環的,那麼原來第二個鍊錶的頭部一定在環上。因此我們就可以從第二個鍊錶的頭部進行遍歷的,從而減少了時間複雜度(減少的時間複雜度是第乙個鍊錶的長度)。

4、仔細研究兩個鍊錶,如果他們相交的話,那麼他們最後的乙個節點一定是相同的,否則是不相交的。因此判斷兩個鍊錶是否相交就很簡單了,分別遍歷到兩個鍊錶的尾部,然後判斷他們是否相同,如果相同,則相交;否則不相交。

判斷出兩個鍊錶相交後就是判斷他們的交點了。假設第乙個鍊錶長度為len1,第二個問len2,然後找出長度較長的,讓長度較長的鍊錶指標向後移動|len1 - len2| (len1-len2的絕對值),然後在開始遍歷兩個鍊錶,判斷節點是否相同即可。

**實現:

#define _crt_secure_no_warnings 1

#include

#include

using namespace std;

typedef struct node

node;

typedef struct node *list;

void in_list(list *head)

void create_list(list *head1, list *head2)

node *find_node(list *head1, list *head2)

node *p1 = *head1;

node *p2 = *head2;

int len1 = 0;

int len2 = 0;

int diff = 0;//絕對值

while (p1->next != null)//求鍊錶1的長度

while (p2->next != null)//求鍊錶2的長度

if (p1 != p2)//如果最後乙個結點不相同,則沒有相交結點

diff = abs(len1 - len2);//len1-len2的絕對值

//長的是p1,短的是p2

if (len1 > len2)

else

for (int i = 0; i < diff; i++)

while (p1 != p2)

return p1;

}int main()

執行結果:

第二種情況:兩個鍊錶中有環

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

如果鍊錶有環且相交,那麼這兩個鍊錶都是有環的。

找到第乙個鍊錶的環點,然後將環斷開(當然不要忘記了儲存它的下乙個節點),然後再來遍歷第二個鍊錶,如果發現第二個鍊錶從有環變成了無環,那麼他們就是相交的嘛,否則就是不相交的了。

當兩個有環的鍊錶相交時,有以下兩種情況:

**實現:

void create_list(list *head1, list *head2)

//求入口結點

node *findentrance(list *head)

if (fast == null || fast->next == null)

return null;

slow = *head;

while (fast != slow)

return fast;

}//求環的長度

int getpathdistance(list *head)

if (fast == null || fast->next == null)

return 0;

node *meet = fast;

slow = slow->next;

fast = fast->next->next;

int distance = 0;

while (slow != fast)

return distance + 1;

}//求鍊錶總長度

int getallpathlen(list *head)

d2 = getpathdistance(head);

d = d1 + d2;

return d;

}//是否帶環

bool i***itloop(list *head)//是否帶環

if (fast == null || fast->next == null)

return false;

return true;

}//帶環鍊錶是否相交

node* find_node(list *head1, list *head2)

else

for (int i = 0; i < diff; i++)

while (p1 != p2)

return p1;

}else

return null;}

執行結果:

在這種情況下,兩個鍊錶的交點在環點之前,可以將環點切斷,這樣就變成了兩個無環的鍊錶求相交點。可使用以上方法。

另一種情況為:

在這種情況下,不存在所謂的相交點。

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

判斷兩個鍊錶是否相交,若相交,求交點。

首先我們來看一下單鏈表 第一種情況 兩個鍊錶均不帶環 判斷兩個不帶環的鍊錶是否相交,如果兩個鍊錶相交的話可如下圖所示 判斷兩個鍊錶是否相交 int isslistcross slistnode phead1,slistnode phead2 相交求交點 兩種方法 法一 因為兩個不帶環鍊錶相交,所以讓...

資料結構 判斷兩個鍊錶是否相交若相交求交點

單鏈表的實現 思路 兩個不帶環的鍊錶相交,則最後乙個結點一定相同。int checkcross plist list1,plist list2 while list2 next if list1 list2 else 思路 利用快慢指標,首先求出兩個鍊錶的長度差n 1,然後讓長的鍊錶先走n 1步。然...

判斷兩個不帶環鍊錶是否相交?若相交,求入口點。

通常情況下,不帶環的兩個鍊錶相交如上圖所示。方法一 1 先判斷鍊錶是否相交 若相交,那麼兩個鍊錶的尾節點必然相同。則可以遍歷兩個鍊錶,判斷其尾節點。若不相交,則尾節點必然不相同。2 若相交,求其入口點 通過遍歷兩個鍊錶可以得到其長度 假設為len1和len2 通過比較len len abs len1...