劍指Offer--037-兩個鏈表的第一個公用結點

來源:互聯網
上載者:User

標籤:

連結

牛客OJ:兩個鏈表的第一個公用結點

九度OJ:http://ac.jobdu.com/problem.php?pid=1505

GitHub代碼: 037-兩個鏈表的第一個公用結點

CSDN題解:劍指Offer–037-兩個鏈表的第一個公用結點

牛客OJ 九度OJ CSDN題解 GitHub代碼
037-兩個鏈表的第一個公用結點 1505-兩個鏈表的第一個公用結點 劍指Offer–037-兩個鏈表的第一個公用結點 037-兩個鏈表的第一個公用結點
題意

題目描述

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

暴力方法

最簡單直接的方法就是,對於第一個鏈表的每個節點,我們依次判斷其是不是第二條鏈表的公用結點

#include <iostream>using namespace std;//  調試開關#define __tmain main#ifdef __tmain#define debug cout#else#define debug 0 && cout#endif // __tmain#ifdef __tmainstruct ListNode{public :    int val;    struct ListNode *next;};#endifclass Solution{public:    ListNode* FindFirstCommonNode(ListNode *leftHead, ListNode *rightHead)    {        ListNode *left = NULL;        ListNode *right = NULL;        //  迴圈第一個鏈表的每個結點        for(left = leftHead;            left != NULL;            left = left->next)        {            debug <<endl <<left->val <<" : ";            //  依次判斷其在不在第二條鏈表中            for(right = rightHead;                right != NULL;                right = right->next)            {                debug <<right->val <<", ";                if(left == right)                {                    break;                }                            }            if(left == right)            {                break;            }        }        return left;    }};int __tmain( ){    ListNode common[2];    common[0].val = 6;    common[0].next = &common[1];    common[1].val = 7;    common[1].next = NULL;    ListNode left[3];    left[0].val = 1;    left[0].next = &left[1];    left[1].val = 2;    left[1].next = &left[2];    left[2].val = 3;    left[2].next = &common[0];    ListNode right[2];    right[0].val = 4;    right[0].next = &right[1];    right[1].val = 5;    right[1].next = &common[0];    Solution solu;    ListNode *node = solu.FindFirstCommonNode(left, right);    while(node != NULL)    {        debug <<node->val <<" ";        node = node->next;    }    debug <<endl;    return 0;}
靠右對齊兩個鏈表

如果兩個鏈表有公用節點,則它們的形狀必然是一個Y字形。

長鏈表先走,實現靠右對齊

先假設這兩個鏈表的長度相等,則我們可以同步遍曆這兩個鏈表,找到公用節點。現在有兩個鏈表,我們可以先分別求齊長度得其差n,然後遍曆長的那個鏈表n個節點,然後同步遍曆這兩個鏈表即可。

class Solution{public:    ListNode* FindFirstCommonNode(ListNode *leftHead, ListNode *rightHead)    {        ListNode *left = leftHead;        ListNode *right = rightHead;        int leftLength = 0;        int rightLength = 0;        ///  首先計算兩個鏈表的長度        leftLength = GetListLength(left);        rightLength = GetListLength(right);        ///  對齊兩個鏈表        int length = 0;        if(leftLength < rightLength)        {            // 右鏈表長            length = rightLength - leftLength;            while(right != NULL && length > 0)            {                right = right->next;                length--;            }        }        else        {            // 左鏈表長            length = leftLength - rightLength;            while(left != NULL && length > 0)            {                left = left->next;                length--;            }        }        //  兩個指標同步移動即可找到共同的結點        while(left != NULL && right != NULL)        {            if(left == right)            {                break;            }            left = left->next;            right = right->next;        }        return ((left == right) ? left : NULL);    }    int GetListLength(ListNode *head)    {        ListNode *node = head;        int length = 0;        while(node != NULL)        {            length++;            node = node->next;        }               return length;    }};
將兩個鏈表拼接起來實現靠右對齊

前面那個思路中,長的鏈表先走一個長度差,從而保證兩個鏈表是靠右對齊的,但是這種方式,我們需要多次掃面鏈表,因為鏈表必須通過掃描才能擷取其長度

但是有沒有不需要多次掃描就可將兩個鏈表對齊的方法呢。

我們可以將兩個鏈表拼接在一起來實現其

left : left->right

>

right : right->left

這樣一來我們的鏈表就成了長度為M+N的兩個鏈表,而公用部分都在最後,而且是對齊的

class Solution{public:    ListNode* FindFirstCommonNode(ListNode *leftHead, ListNode *rightHead)    {        ListNode *left= leftHead;        ListNode *right = rightHead;        debug <<(left == NULL ? -1 : left->val) <<", ";        debug <<(right == NULL ? -1 : right->val) <<endl;        while(left != right)        {            left = (left == NULL ? rightHead : left->next);            right = (right == NULL ? leftHead : right->next);            debug <<(left == NULL ? -1 : left->val) <<", ";            debug <<(right == NULL ? -1 : right->val) <<endl;        }        return left;    }};
棧的後進先出實現靠右對齊

由於棧是後進先出的,因此我們將兩個鏈表分別入棧,那麼棧頂的元素一定是最後一個元素。從而兩個鏈表是靠右對齊的,兩個棧同步彈出,當兩個棧頂的節點不相同時候,即是開始合并的前一個節點

class Solution{public:    ListNode* FindFirstCommonNode(ListNode *leftHead, ListNode *rightHead)    {        ListNode *left = leftHead;        ListNode *right = rightHead;        stack<ListNode *> leftStack;        stack<ListNode *> rightStack;        /// 結點依次入棧        while(left != NULL)        {            //debug <<left->val <<endl;            leftStack.push(left);            left = left->next;        }        while(right != NULL)        {            //debug <<right->val <<endl;            rightStack.push(right);            right = right->next;        }        ///  開始同步彈出元素        while(leftStack.empty( ) != true           && rightStack.empty( ) != true)        {            left = leftStack.top( );            right = rightStack.top( );            debug <<left->val <<", " <<right->val <<endl;            ///  不相同的元素就是合并的前一個結點            if(left != right)            {                break;            }            leftStack.pop( );            rightStack.pop( );        }        ///  不相同元素的下一個結點就是共同結點        if(left != right)        {            return left->next;        }        else        {            return NULL;        }    }};
利用高效的資料結構實現尋找結點

當然還有其他思路,我們可以使用一個尋找效率高的資料結構,比如hash或者map

>

先將第一個鏈表插入,然後因此判斷第二個鏈表的節點在不在map中,即可尋找到第一個共同結點

利用unordered_map,這個模板類是基於hash表實現的,速度與map、hashmap相比較快

class Solution{public:    ListNode* FindFirstCommonNode(ListNode *leftHead, ListNode *rightHead)    {        unordered_map<ListNode*, bool> umap;        ListNode* left = leftHead;        while (left != NULL)        {            umap.insert(make_pair(left, 1 ));            left = left->next;        }        ListNode* right = rightHead;        while (right)        {            if (umap.count(right)>0)            {                return right;            }            right = right->next;        }        return NULL;    }};

劍指Offer--037-兩個鏈表的第一個公用結點

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.