判斷兩個鏈表是否相交


1 假設兩個鏈表都沒有環

解題思路

a. 直接循環判斷第一個鏈表的每個節點是否在第二個鏈表中。但,這種方法的時間復雜度為O(Length(h1) * Length(h2))。顯然,我們得找到一種更為有效的方法,至少不能是O(N^2)的復雜度。

b. 針對第一個鏈表直接構造hash表,然后查詢hash表,判斷第二個鏈表的每個節點是否在hash表出現,如果所有的第二個鏈表的節點都能在hash表中找到,即說明第二個鏈表與第一個鏈表有相同的節點。時間復雜度為為線性:O(Length(h1) + Length(h2)),同時為了存儲第一個鏈表的所有節點,空間復雜度為O(Length(h1))。是否還有更好的方法呢,既能夠以線性時間復雜度解決問題,又能減少存儲空間?

 

c.轉換為環的問題。把第二個鏈表接在第一個鏈表后面,如果得到的鏈表有環,則說明兩個鏈表相交。如何判斷有環的問題上面已經討論過了,但這里有更簡單的方法。因為如果有環,則第二個鏈表的表頭一定也在環上,即第二個鏈表會構成一個循環鏈表,我們只需要遍歷第二個鏈表,看是否會回到起始點就可以判斷出來。這個方法的時間復雜度是線性的,空間是常數。

 

d.進一步考慮“如果兩個沒有環的鏈表相交於某一節點,那么在這個節點之后的所有節點都是兩個鏈表共有的”這個特點,我們可以知道,如果它們相交,則最后一個節點一定是共有的。而我們很容易能得到鏈表的最后一個節點,所以這成了我們簡化解法的一個主要突破口。那么,我們只要判斷兩個鏈表的尾指針是否相等。相等,則鏈表相交;否則,鏈表不相交。

所以,先遍歷第一個鏈表,記住最后一個節點。然后遍歷第二個鏈表,到最后一個節點時和第一個鏈表的最后一個節點做比較,如果相同,則相交,否則,不相交。這樣我們就得到了一個時間復雜度,它為O((Length(h1) + Length(h2)),而且只用了一個額外的指針來存儲最后一個節點。這個方法時間復雜度為線性O(N),空間復雜度為O(1),顯然比解法三更勝一籌

2 假設兩個鏈表都有環,情況只有2種:相交於”環上”或相交於”不是環的部分”。因此環一定是在公共部分上的。假如知道其中一個鏈表上環的任意一個節點,則只需要判斷是否在另一個鏈表上就行了。這里有個疑問?一般意義上,鏈表有環並不存在這種形式:1->2->3->2->4?

帶環單向鏈表相交只有2種情況

 

//判斷帶環不帶環時鏈表是否相交  
//2.如果都不帶環,就判斷尾節點是否相等  
//3.如果都帶環,判斷一鏈表上倆指針相遇的那個節點,在不在另一條鏈表上。  
bool detect(Node * head1, Node * head2)  
{  
    Node * circleNode1;  
    Node * circleNode2;  
    Node * lastNode1;  
    Node * lastNode2;  
      
    bool isCircle1 = isCircle(head1,circleNode1, lastNode1);  
    bool isCircle2 = isCircle(head2,circleNode2, lastNode2);  
      
    //一個有環,一個無環  
    if(isCircle1 != isCircle2)  
        return false;  
    //兩個都無環,判斷最后一個節點是否相等  
    else if(!isCircle1 && !isCircle2)  
    {  
        return lastNode1 == lastNode2;  
    }  
    //兩個都有環,判斷環里的節點是否能到達另一個鏈表環里的節點  
    else  
    {  
        Node * temp = circleNode1->next;  //updated,多謝蒼狼 and hyy。  
        while(temp != circleNode1)    
        {  
            if(temp == circleNode2)  
                return true;  
            temp = temp->next;  
        }  
        return false;  
    }  
      
    return false;  
}  

 

3   求相交的第一個元素

對於1中相交,只要知道兩個鏈表長度L1和L2,那么讓長的那個先走abs(L1-L2),然后一起走,相同的那個節點就是第一個元素

//求兩鏈表相交的第一個公共節點
Node* findIntersectNode(Node *h1,Node *h2)
{
    int len1 = listLength(h1);          //求鏈表長度
    int len2 = listLength(h2);
    //對齊兩個鏈表
    if(len1 > len2)
    {
        for(int i=0;i<len1-len2;i++)
            h1=h1->next;
    }
    else 
    {
        for(int i=0;i<len2-len1;i++)
            h2=h2->next;
    }

    while(h1 != NULL)
    {
        if(h1 == h2)
            return h1;
        h1 = h1->next;
        h2 = h2->next;    
    }
    return NULL;
}

http://wuchong.me/blog/2014/03/25/interview-link-questions/

http://blog.csdn.net/v_july_v/article/details/6447013


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM