相交鏈表

題目鏈接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/

方法一: 暴力法

對鏈表A中的每一個結點ai,遍歷整個鏈表 B 並檢查鏈表 B 中是否存在結點和ai相同。

複雜度分析

時間複雜度 : (mn)。
空間複雜度 : O(1)O(1)。



方法二: 哈希表法

遍歷鏈表 A 並將每個結點的地址/引用存儲在哈希表中。然後檢查鏈表 B 中的每一個結點bi是否在哈希表中。若在,則bi爲相交結點。

複雜度分析

時間複雜度 : O(m+n)O(m+n)。
空間複雜度 : O(m)O(m) 或 O(n)O(n)。



方法三:雙指針法
創建兩個指針 pApA 和 pBpB,分別初始化爲鏈表 A 和 B 的頭結點。然後讓它們向後逐結點遍歷。
當 pApA 到達鏈表的尾部時,將它重定位到鏈表 B 的頭結點 (你沒看錯,就是鏈表 B); 類似的,當 pBpB 到達鏈表的尾部時,將它重定位到鏈表 A 的頭結點。
若在某一時刻 pApA 和 pBpB 相遇,則 pApA/pBpB 爲相交結點。
想弄清楚爲什麼這樣可行, 可以考慮以下兩個鏈表: A={1,3,5,7,9,11} 和 B={2,4,9,11},相交於結點 9。 由於 B.length (=4) < A.length (=6),pBpB 比 pApA 少經過 22 個結點,會先到達尾部。將 pBpB 重定向到 A 的頭結點,pApA 重定向到 B 的頭結點後,pBpB 要比 pApA 多走 2 個結點。因此,它們會同時到達交點。
如果兩個鏈表存在相交,它們末尾的結點必然相同。因此當 pApA/pBpB 到達鏈表結尾時,記錄下鏈表 A/B 對應的元素。若最後元素不相同,則兩個鏈表不相交。
複雜度分析
時間複雜度 : O(m+n)O(m+n)。
空間複雜度 : O(1)O(1)。

下面代碼思路:

我們需要做的事情是,讓兩個鏈表從同距離末尾同等距離的位置開始遍歷。這個位置只能是較短鏈表的頭結點位置。
爲此,我們必須消除兩個鏈表的長度差

指針 pA 指向 A 鏈表,指針 pB 指向 B 鏈表,依次往後遍歷
如果 pA 到了末尾,則 pA = headB 繼續遍歷
如果 pB 到了末尾,則 pB = headA 繼續遍歷
比較長的鏈表指針指向較短鏈表head時,長度差就消除了
如此,只需要將最短鏈表遍歷兩次即可找到位置
聽着可能有點繞,看圖最直觀,鏈表的題目最適合看圖了

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
                if(headA == null || headB == null){
            return null;
        }

        ListNode pA = headA,pB = headB;

        while(pA != pB){
            pA = pA == null? headB : pA.next;
            pB = pB == null? headA : pB.next;
        }
        return pA;
    }
}

 

發佈了65 篇原創文章 · 獲贊 13 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章