兩個連結串列的第一個公共節點

皮卡qiu~發表於2020-11-26

一、需求

  • 輸入兩個連結串列,找出它們的第一個公共節點。
  • 如下面的兩個連結串列

       

  • 在節點 c1 開始相交。

二、雙指標(暴力)

2.1  思路分析

  1. 採用雙重迴圈,使用兩個指標p、q分別指向連結串列A和連結串列B,外迴圈遍歷連結串列A,內迴圈遍歷連結串列B,每次判斷當前連結串列A的節點是否就是當前連結串列B的節點,如果是就返回該節點,否則就一直遍歷,直到連結串列A遍歷結束;
  2. 如果不存在公共結點,則返回null;
  3. 因為本題要求時間複雜度限制在O(1),故該方法在執行時會出現超時;

2.2  程式碼實現

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p = headA;
        while(p != null) {
            ListNode q = headB;
            while(q != null) {
                if(p == q) return p;
                q = q.next;
            }
            p = p.next;
        }
        return null;
    }
}

2.3  複雜度分析

  • 時間複雜度為O(n^2),因為採用了雙重迴圈,計算次數為n^2;
  • 空間複雜度為O(1),變數p,q佔用常數大小的額外空間;

三、雙指標法(優化)

3.1  思路分析

  1. 假設連結串列A、B存在公共節點,連結串列A頭節點距離公共節點為L1步,即[A頭節點,公共節點),連結串列B頭節點距離公共節點為L2步,即[B頭節點,公共節點),兩個連結串列的公共部分長度為C;
  2. 那麼根據L1+C+L2 = L2+C+L1的原理,設指標p,q指向連結串列A,B,p,q同時移動,當p走過L1+C+L2後,q走過L2+C+L1後,它們會在公共結點相遇;

3.2  程式碼實現

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p = headA;
        ListNode q = headB;
        while(p != q) {
            //這裡讓雙指標同時移動,避免了迴圈
            p = p != null ? p.next : headB;
            q = q != null ? q.next : headA;
        }
        return p;
    }
}

3.3  複雜度分析

  • 時間複雜度為O(n);
  • 空間複雜度為O(1);

四、學習地址

作者:腐爛的橘子

連結:https://leetcode-cn.com/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/solution/shuang-zhi-zhen-fa-lang-man-xiang-yu-by-ml-zimingm/

相關文章