劍指Offer(Java版):兩個鏈表的第一個公共結點

題目:輸入兩個鏈表,找出它們的第一個公共結點。面試

面試的時候碰到這道題,不少應聘者的第一反應就是蠻力法:在第一鏈表 上順序遍歷每一個結點,沒遍歷到一個結點的時候,在第二個鏈表上順序遍歷每一個結點。若是在第二個鏈表上有一個結點和第一個鏈表上的結點同樣,說明兩個鏈表在 這個結點上重合,因而就找到了他們的公共結點。若是第一個鏈表的長度爲m,第二個鏈表的長度爲n,顯然該方法的時間複雜度爲O(mn).get

一般蠻力法不會是最好的辦法,咱們接下來試着分析有公共結點的兩個鏈 表有哪些特色。從鏈表結點的定義能夠看出,這兩個鏈表是單鏈表。若是兩個單向鏈表有公共的結點,那麼這兩個鏈表從某一結點開始,它們的m_pNext都指 向同一個結點,但因爲是單向鏈表的結點,以後他們全部結點都是重合的,不可能再出現分叉。因此兩個有公共結點而部分重合的鏈表,拓撲形狀開起來像一個Y, 而不可能項X。class

通過分析咱們發現,若是兩個鏈表有公共結點,那麼公共結點出如今兩個 鏈表的尾部。若是咱們從兩個鏈表的尾部開始往前比較,最後一個相同的結點就是咱們要找的結點。可問題是在單向鏈表中,咱們只能從頭結點開始按順序遍歷,最 後才能到達尾節點。最後到達的尾節點卻要最早被比較,這聽起來是否是像後進先出,也是咱們就能想到用棧的特色來解決這個問題:分別把兩個鏈表的結點放入兩 個棧裏,這樣兩個鏈表的尾節點就位於兩個棧的棧頂,接下來比較兩個棧頂的結點是否相同。若是相同,則把棧頂彈出接着比較下一個棧頂,直到找到最後一個相同 的結點。test

在上述思路中,咱們須要用兩個輔助棧。若是鏈表的長度分別爲m和n,那麼空間複雜度是O(m+n)。這種思路的時間複雜度也是O(m+n).和最開始的蠻力法相比,時間效率獲得了提升,至關因而用空間消耗換取了時間效率。效率

之因此須要用到棧,是由於咱們想同時遍歷到達兩個棧的尾節點。當兩個 鏈表的長度不相同時,若是咱們從頭開始遍歷到達兩個棧的尾節點的時間就不一致。其實解決這個問題還有一個更簡單的辦法:首先遍歷兩個鏈表獲得他們的長度, 就能知道哪一個鏈表比較長,以及長的鏈表比短的鏈表多幾個結點。在第二次遍歷的時候,在較長的鏈表上先走若干步,接着再同時在兩個鏈表上遍歷,找到第一個相 同的結點就是他們的第一個公共結點。List

第三種思路比第二種思路相比,時間複雜度爲O(m+n),但咱們不在須要輔助棧,所以提升了空間效率。當面試官確定了咱們的最後一個思路的時候,能夠動手寫代碼了。遍歷

Java代碼實現:方法

package cglib;im

class ListNode{
    int data;
    
    ListNode nextNode;
    
}鏈表

public class jiekou {

    
        public static void main(String[] args) {
        ListNode head1=new ListNode();
        ListNode second1=new ListNode();
        ListNode third1=new ListNode();
        ListNode forth1=new ListNode();
        ListNode fifth1=new ListNode();
        ListNode head2=new ListNode();
        ListNode second2=new ListNode();
        ListNode third2=new ListNode();
        ListNode forth2=new ListNode();
        head1.nextNode=second1;
        second1.nextNode=third1;
        third1.nextNode=forth1;
        forth1.nextNode=fifth1;
        head2.nextNode=second2;
        second2.nextNode=forth1;
        third2.nextNode=fifth1;
        head1.data=1;
        second1.data=2;
        third1.data=3;
        forth1.data=6;
        fifth1.data=7;
        head2.data=4;
        second2.data=5;
        third2.data=6;
        forth2.data=7;
        jiekou test=new jiekou();
        System.out.println(test.findFirstCommonNode(head1, head2).data);
        }
        public ListNode findFirstCommonNode(ListNode head1,ListNode head2){
        int len1=getListLength(head1);
        int len2=getListLength(head2);
        ListNode longListNode=null;
        ListNode shortListNode=null;
        int dif=0;
        if(len1>len2){
        longListNode=head1;
        shortListNode=head2;
        dif=len1-len2;
        }else{
        longListNode=head2;
        shortListNode=head1;
        dif=len2-len1;
        }
        for(int i=0;i<dif;i++){ longListNode=longListNode.nextNode;
        }
        while(longListNode!=null&&shortListNode!=null
        &&longListNode!=shortListNode){ longListNode=longListNode.nextNode; shortListNode=shortListNode.nextNode;
        }
        return longListNode;
        }
        private int getListLength(ListNode head1) {
        int result=0;
        if(head1==null)
        return result;
        ListNode point=head1;
        while(point!=null){
        point=point.nextNode;
        result++;
        }
        return result;
        }

    }
   

輸出:6

相關文章
相關標籤/搜索