数据结构-剑指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;
    }
};

猜你喜欢

转载自blog.csdn.net/baidu_32936911/article/details/80311073
今日推荐