數據結構-劍指offer-兩個鏈表的第一個公共節點

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

思路1:暴力查找法。將鏈表1中的節點逐個與鏈表2中的所有節點比較,返回第一個相同的節點。複雜度O(mn)

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(pHead1 == nullptr || pHead2 == nullptr){
            return nullptr;
        }
        ListNode* pNode1 = pHead1;
        ListNode* pNode2 = pHead2;
        ListNode* pCommonNode = nullptr;
        while(pNode1->next != nullptr){
            while(pNode2->next !=nullptr){
                if(pNode1 != pNode2){
                     pNode2 = pNode2->next;
                }
                else{
                    pCommonNode = pNode1;
                    return pCommonNode;
                    break;
                }
            }
            if(pCommonNode != nullptr){
                break;
            }
            else{
                pNode1 = pNode1->next;
            }
        }
        return pCommonNode;
    }
};

上述代碼沒有通過測試用例:具體原因是什麼呢???

思路2:上述方法的複雜度過高,並不是一個好方法。如果兩個鏈表有公共點,那麼公共節點出現在兩個鏈表的尾部。如果從兩個鏈表的尾部開始往前比較,那麼最後一個相同的節點就是我們要找的節點。因爲要從尾部開始比較,所以可以利用棧結構的“後進後出”:分別把兩個鏈表的節點放入兩個棧中,這樣兩個棧的尾節點就位於兩個棧的棧頂,接下來比較兩個棧頂的節點是否相同,相同則把棧頂彈出接着比較下一個棧頂,直到找到最後一個相同節點。這種方法是用空間消耗換取了時間效率。

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(pHead1 == nullptr || pHead2 == nullptr){
            return nullptr;
        }
        std::stack<ListNode*> stack1;
        std::stack<ListNode*> stack2;
        while(pHead1 != nullptr){
            stack1.push(pHead1);
            pHead1=pHead1->next;
        }
        while(pHead2 != nullptr){
            stack2.push(pHead2);
            pHead2=pHead2->next;
        }
        ListNode* commonNode = nullptr;
        while(!stack1.empty() && !stack2.empty()){
            if(stack1.top()  == stack2.top()){
                commonNode = stack1.top();
                stack1.pop();
                stack2.pop();
            }
        }
        return commonNode;
    }
};

報錯:


思路3:首先遍歷兩個鏈表得到它們的長度,就能知道哪個鏈表比較長,以及長得鏈表比短的鏈表多幾個節點。在第二次遍歷的時候,在較長的鏈表上先走若干步,接着同時在兩個鏈表上遍歷,找到的第一個相同的節點就是它們的第一個公共節點。

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        unsigned int nLength1 = GetListLength(pHead1);
        unsigned int nLength2 = GetListLength(pHead2);
        int nLengthDif = nLength1 - nLength2;
        ListNode* pListNodeLong = pHead1;
        ListNode* pListNodeShort = pHead2;
        if(nLength2>nLength1){
            pListNodeLong = pHead2;
            pListNodeShort = pHead1;
            nLengthDif = nLength2 - nLength1;
        }
        for(int i = 1;i<nLengthDif+1;i++){
            pListNodeLong = pListNodeLong->next;
        }
        while(pListNodeLong != nullptr && pListNodeShort != nullptr && pListNodeShort != pListNodeLong){
            pListNodeLong = pListNodeLong->next;
            pListNodeShort = pListNodeShort->next;
        }
        ListNode* pFirstCommonNode = pListNodeLong;
        return pFirstCommonNode;
    }
private:
    unsigned int GetListLength(ListNode * pHead){
        unsigned int nLength = 0;
        ListNode* pNode = pHead;
        while(pNode != nullptr){
            nLength++;
            pNode = pNode->next;
        }
        return nLength;
    }
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章