剑指offer学习笔记 两个链表的第一个公共节点

面试题52:两个链表的第一个公共节点。输入两个链表,找出它们的第一个公共节点,链表节点定义如下:

struct ListNode {
    int m_nKey;
    ListNode* m_pNext;
};

蛮力法:在第一个链表上顺序遍历每个节点,每遍历到一个节点,就在第二个链表上顺序遍历每个节点,直到找到第一个公共节点,如果第一个链表长为m,第二个链表长度为n,那么时间复杂度为O(mn),太慢了。

法二:我们可以把两个链表分别放到两个栈中,而栈顶元素一定是一样的,因为最后一个元素一定是公共的节点,接着从两个栈中出栈一个元素,再比较栈顶元素,直到两个栈顶元素不同,那么上次出栈的节点即为第一个公共节点。这种方法的时间复杂度为O(m+n),空间复杂度也是O(m+n),与蛮力法相比,时间效率得到了提高,但是以牺牲空间效率为代价。

法三:法二牺牲了空间效率换来了时间性能的提升,也可以先遍历两个链表,从而得到长度,即得到了两链表的长度差,之后长的往前走长度差个步数,之后两个链表再一起向尾部遍历,直到找到第一个相同的节点。这种方法时间复杂度也是O(m+n),但不需要辅助栈:

#include <iostream>
using namespace std;

struct ListNode {
    int m_nKey;
    ListNode* m_pNext;
};

int GetListLength(ListNode* head) {
    ListNode* pNode = head;
    int count = 0;
    while (pNode != nullptr) {
        ++count;
        pNode = pNode->m_pNext;
    }
    return count;
}

ListNode* FindFirstCommonNode(ListNode* head1, ListNode* head2) {
    if (head1 == nullptr || head2 == nullptr) {
        return nullptr;
    }

    int length1 = GetListLength(head1);
    int length2 = GetListLength(head2);

    ListNode* longList = head1;
    ListNode* shortList = head2;
    int lengthDif = length1 - length2;

    if (length1 < length2) {
        longList = head2;
        shortList = head1;
        lengthDif = -lengthDif;
    }

    while (lengthDif > 0) {
        longList = longList->m_pNext;
        --lengthDif;
    }

    while (longList != nullptr) {
        if (longList == shortList) {
            break;
        }
        longList = longList->m_pNext;
        shortList = shortList->m_pNext;
    }
    return longList;
}

int main() {
    ListNode* pNode1 = new ListNode();
    ListNode* pNode2 = new ListNode();
    ListNode* pNode3 = new ListNode();
    ListNode* pNode4 = new ListNode();
    ListNode* pNode5 = new ListNode();
    ListNode* pNode6 = new ListNode();
    ListNode* pNode7 = new ListNode();

    pNode1->m_nKey = 1;
    pNode2->m_nKey = 2;
    pNode3->m_nKey = 3;
    pNode4->m_nKey = 4;
    pNode5->m_nKey = 5;
    pNode6->m_nKey = 6;
    pNode7->m_nKey = 7;

    pNode1->m_pNext = pNode2;
    pNode2->m_pNext = pNode3;
    pNode3->m_pNext = pNode6;
    pNode4->m_pNext = pNode5;
    pNode5->m_pNext = pNode6;
    pNode6->m_pNext = pNode7;
    pNode7->m_pNext = nullptr;

    ListNode* commonNode = FindFirstCommonNode(pNode1, pNode4);
    if (commonNode) {
        cout << "第一个公共节点值为:" << commonNode->m_nKey << endl;
    }
    else {
        cout << "没有公共节点。" << endl;
    }
}
发布了211 篇原创文章 · 获赞 11 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/tus00000/article/details/105198947