【LeetCode】【連結串列】劍指 Offer 52. 兩個連結串列的第一個公共節點 思路解析和程式碼

九筒-發表於2020-12-14

劍指 Offer 52. 兩個連結串列的第一個公共節點

題目連結

個人思路

思路

暴力O(mn)

雙重迴圈求解,對比兩個鏈中的每一個節點

棧-空間換時間O(m+n),空間(m+n)

由於第一個公共節點後面的所有節點均相等,因此可以從後往前遍歷,直到找到最後一個相同的結點即為第一個公共節點,但由於單向連結串列無法逆序遍歷,因此可以考慮使用棧輔助完成

雙指標O(m+n)

  • 先遍歷兩個連結串列,得到兩個連結串列的長度
  • 求出長度之差temp
  • 在較長的連結串列中,先遍歷temp個結點,然後兩個連結串列一同遍歷,此時碰到的第一個相同的結點即為第一個公共節點

注意

  • 雙指標在連結串列中的應用:雙指標可以從固定兩個指標之間的間距作為切入點來解決兩個連結串列的第一個公共節點問題和連結串列中倒數第k個元素的問題

個人思路程式碼

暴力

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA == NULL || headB == NULL){
            return NULL;
        }
        if(headA == headB){
            return headA;
        }
        ListNode *curA = headA, *curB = headB;
        ListNode *ans = NULL;
        bool flag = false;
        while(curA != NULL){
            if(flag == true)
                break;
            curB = headB;
            while(curB != NULL){
                if(curA == curB){
                    ans = curA;
                    flag = true;
                    break;
                }
                // cout << curA->val << " " << curB->val << endl;
                curB = curB->next;
            }
            curA = curA->next;
            // cout << curA->val << " " << curA->next << endl;
        }
        return ans;
    }
};

在這裡插入圖片描述

棧——以空間換時間

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    stack<ListNode*> sA;//時間換空間
    stack<ListNode*> sB;
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA == NULL || headB == NULL){
            return NULL;
        }
        ListNode *cur = headA;
        while(cur != NULL){
            sA.push(cur);
            cur = cur->next;
        }
        cur = headB;
        while(cur != NULL){
            sB.push(cur);
            cur = cur->next;
        }
        ListNode *ans = NULL;
        if(sA.top() == sB.top()){
            ans = sA.top();//先記錄最後一個相同的結點
        }else{
            return ans;
        }
        while(!sA.empty() && !sB.empty()){
            if(sA.top() != sB.top()){//尋找第一個不相同的結點
                break;
            }else{
                ans = sA.top();
            }
            sA.pop();
            sB.pop();
        }
        return ans;
    }
};

在這裡插入圖片描述

雙指標

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *compareLists(ListNode *longer, ListNode *shorter, int temp){
        ListNode *curLonger = longer, *curShorter = shorter, *res = NULL;
        for(int i = 0; i < temp; ++i){
            curLonger = curLonger->next;
        }
        while(curLonger != NULL && curShorter != NULL){
            if(curLonger == curShorter){
                res = curLonger;
                break;
            }
            curLonger = curLonger->next;
            curShorter = curShorter->next;
        }
        return res;
    }
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA == NULL || headB == NULL){
            return NULL;
        }
        int lenA = 0, lenB = 0;
        ListNode *cur = headA, *ans = NULL;
        while(cur != NULL){
            lenA++;
            cur = cur->next;
        }
        cur = headB;
        while(cur != NULL){
            lenB++;
            cur = cur->next;
        }
        // cout << lenA << " " << lenB << endl;
        if(lenA > lenB){
            ans = compareLists(headA, headB, lenA - lenB);
        }else{
            ans = compareLists(headB, headA, lenB - lenA);
        }
        return ans;
    }
};

在這裡插入圖片描述

相關文章