《編程之美》兩鏈表相交及擴充詳解

來源:互聯網
上載者:User

 《編程之美》兩鏈表相交及擴充詳解:

給定一個單鏈表,只給出頭指標h:

1、如何判斷是否存在環?

2、如何知道環的長度?

3、如何找出環的連接點在哪裡?

4、帶環鏈表的長度是多少? 

解法:

1、對於問題1,使用追趕的方法,設定兩個指標slow、fast,從頭指標開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到NULL退出。

2、對於問題2,記錄下問題1的碰撞點p,slow、fast從該點開始,再次碰撞所走過的運算元就是環的長度s。

3、問題3:有定理:碰撞點p到連接點的距離=頭指標到連接點的距離,因此,分別從碰撞點、頭指標開始走,相遇的那個點就是連接點。

設h走到c的長度為a,s走到p的長度為b,p走到的s長度為c。則相當於2個人從h節點開始,分別以1和2的速度走,相遇點為p,則第一個人走的時間為h->s->p的時間(a+b),第二個人在該時間內走的距離則為2(a+b),而它走的路線為h->s->p->s->p,即比第一個人多走了一個環的長度,距離為(a+b+c+b)。則由2(a+b)= (a+b+c+b),可得a=c,即ps=hs,即證。

4、問題3中已經求出連接點距離頭指標的長度,加上問題2中求出的環的長度,二者之和就是帶環單鏈表的長度。

 

判斷是否存在環的程式:

bool IsExitsLoop(slist *head) 

    slist *slow = head, *fast = head; 

 

    while ( fast && fast->next )  

    { 

        slow = slow->next; 

        fast = fast->next->next; 

        if ( slow == fast ) break; 

    } 

 

    return !(fast == NULL || fast->next == NULL); 

bool IsExitsLoop(slist *head)

{

    slist *slow = head, *fast = head;

 

    while ( fast && fast->next )

    {

        slow = slow->next;

        fast = fast->next->next;

        if ( slow == fast ) break;

    }

 

    return !(fast == NULL || fast->next == NULL);

}

 

尋找環連接點(進入點)的程式:

slist* FindLoopPort(slist *head) 

    slist *slow = head, *fast = head; 

 

    while ( fast && fast->next )  

    { 

        slow = slow->next; 

        fast = fast->next->next; 

        if ( slow == fast ) break; 

    } 

 

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

        return NULL; 

 

    slow = head; 

    while (slow != fast) 

    { 

         slow = slow->next; 

         fast = fast->next; 

    } 

 

    return slow; 

}

 

《編程之美》裡面有一篇是講如何判斷兩鏈表是否相交,讀後覺得原文太過囉嗦。於是,筆者總結了一下,此類問題可以擴充為兩大類,分別是:

1、單鏈表與環問題http://blog.csdn.net/liuxialong/archive/2011/06/20/6555850.aspx

2、單鏈表相交與環問題(本文)

--------------------------------------------------------------------------------

 

給定兩單鏈表A、B,只給出兩頭指標。請問:

1、如何判斷兩單鏈表(無環)是否相交?

有兩種可取的辦法:

(1)人為構環,將鏈表A的尾節點指向鏈表B,再判斷是否構環成功?從鏈表B的頭指標往下遍曆,如果能夠回到B,則說明相交

(2)判斷兩鏈表最後一個節點是否相同,如果相交,則尾節點肯定是同一節點

 

2、如何判斷兩單鏈表(不知是否有環)相交?

先判斷是否有環,判斷是否有環可以使用追逐辦法,設定兩個指標,一個走一步,一個走兩步,如果能相遇則說明存在環

(1)兩個都沒環:回到問題1

(2)一個有環,一個沒環:不用判斷了,肯定兩鏈表不相交

(3)兩個都有環:判斷鏈表A的碰撞點是否出現在鏈表B的環中,如果在,則相交。(相交時,環必定是兩鏈表共有的)

 

3、如何尋找兩相交鏈表(不知是否有環)的第一個相交節點?

同樣,使用追逐辦法先判斷是否存在環,分情況討論

(1)無環:人為構環,將鏈表A的尾節點指向鏈表B,則構成一個帶環的單鏈表。這個問題就轉換成尋找帶環單鏈表的環入口節點。

    解法參考:http://blog.csdn.net/liuxialong/archive/2011/06/20/6555850.aspx

 

(2)有環:計算出兩鏈表的長度lA、lB,(環的長度和環到進入點長度之和就是鏈表長度)

計算帶環鏈表長度,可參考http://blog.csdn.net/liuxialong/archive/2011/06/20/6555850.aspx

如果lA>lB,則鏈表A指標先走lA-lB,然後鏈表B指標開始走,兩者相遇的點就是相交點

如果lB>lA,則鏈表B指標先走lB-lA,然後鏈表A指標開始走,兩者相遇的點就是相交點

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.