劍指Offer對答如流系列 - 兩個鏈表的第一個公共結點

面試題52:兩個鏈表的第一個公共結點

一、題目描述

輸入兩個鏈表,找出它們的第一個公共結點。

鏈表節點定義如下:

	public class ListNode{
        int val;
        ListNode next = null;
        ListNode(int val) {
            this.val = val;
        }
    }

在這裏插入圖片描述

二、問題分析

最直接的手段是暴力法,遍歷第一個鏈表的結點,每到一個結點,就在第二個鏈表上遍歷每個結點,判斷是否相等。時間複雜度爲O(m*n),效率低,面試中這種解法肯定不會讓面試官滿意。

我們需要點技巧,我們列舉一下吧

方法一:
使用棧:由於公共結點可以從尾部進行判斷,所以用兩個棧分別放入兩個鏈表中的結點,從尾結點開始出棧比較。時間複雜度O(m+n),空間複雜度O(m+n)。

方法二:
之前我們做過劍指Offer對答如流系列 - 鏈表中倒數第k個結點
可以利用長度關係:計算兩個鏈表的長度之差,長鏈表先走相差的步數,之後長短鏈表同時遍歷,找到的第一個相同的結點就是第一個公共結點。

方法三:
之前我們做過劍指Offer對答如流系列 - 鏈表中環的入口節點
利用兩個引用:一個引用順序遍歷list1和list2,另一個引用順序遍歷list2和list1,(這樣兩引用能夠保證最終同時走到尾結點),兩個引用找到的第一個相同結點就是第一個公共結點。

三、問題解答

利用長度關係的解法:

public ListNode findFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        
        int length1 = getLength(pHead1);
        int length2 = getLength(pHead2);
        int lengthDif = length1-length2;
        ListNode longList = pHead1;
        ListNode shortList = pHead2;
        
        if(lengthDif<0){
            longList = pHead2;
            shortList = pHead1;
            lengthDif = -lengthDif;
        }
        
        for(int i=0;i<lengthDif;i++) {
            longList = longList.next;
        }
           
        while(longList!=null && longList!=shortList ){
            longList=longList.next;
            shortList=shortList.next;
        }
        return longList;  //沒有公共結點剛好是null
    }

    private int getLength(ListNode head){
        int len=0;
        while(head!=null){
            len++;
            head=head.next;
        }
        return len;
    }

利用兩個引用的解法

   public ListNode findFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode p1=pHead1;
        ListNode p2=pHead2;
        while(p1!=p2){
            p1= (p1==null ? pHead2 : p1.next);
            p2= (p2==null ? pHead1 : p2.next);
        }
        return p1;
    }
發佈了194 篇原創文章 · 獲贊 3472 · 訪問量 53萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章