• 面试题52:两个链表的第一个公共节点


    输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

    解题思路

    • 暴力枚举(O(m*n))
    • 辅助栈(两个栈)
    • 双指针(O(m+n))

    上代码(C++很香)

    法一:暴力枚举
    ListNode* FindFirstCommonNodeBL( ListNode* pHead1, ListNode* pHead2) {
        ListNode* pNode1 = pHead1;
        ListNode* pNode2 = pHead2;
        while(pNode1 != nullptr){
            pNode2 = pHead2;
            while(pNode2 != nullptr){
                if(pNode1 == pNode2)
                    return pNode1;
                pNode2 = pNode2->next;
            }
            pNode1 = pNode1->next;
        }
        return nullptr;
    }
    
    法二:辅助栈

      注意,在判断栈顶元素的时候,直到栈顶元素不相等时,可能是找到了第一个相等的节点,也可能是没有相等的节点。

    ListNode *FindFirstCommonNode(ListNode *headA, ListNode *headB){
        if(headA == nullptr || headB == nullptr)
            return nullptr;
        ListNode* p = headA;
        ListNode* q = headB;
        stack<ListNode* > stack_a;
        stack<ListNode* > stack_b;
        while(p != nullptr){
            stack_a.push(p);
            p = p->next;
        }
        while(q != nullptr){
            stack_b.push(q);
            q = q->next;
        }
        int sizeA = stack_a.size();
        int tmp = 0;
        while(!stack_a.empty() && !stack_b.empty()){
            if(stack_a.top() != stack_b.top())
                break;
            else{
                stack_a.pop();
                stack_b.pop();
                tmp++;
            }
        }
        tmp = sizeA - tmp;
        p = headA;
        while(tmp--)
            p = p->next;
    
        return p;
    }
    
    法三:双指针(很妙)

    这里先假设链表A头结点与结点8的长度 与 链表B头结点与结点8的长度相等,那么就可以用双指针。

    1. 初始化:指针ta指向链表A头结点,指针tb指向链表B头结点
    2. 如果ta == tb, 说明找到了第一个公共的头结点,直接返回即可。
    3. 否则,ta != tb,则++ta,++tb

    所以现在的问题就变成,如何让本来长度不相等的变为相等的?
    假设链表A长度为a, 链表B的长度为b,此时a != b
    但是,a+b == b+a
    因此,可以让a+b作为链表A的新长度,b+a作为链表B的新长度。

    // 双指针法
    ListNode* FindFirstCommonNodeDouble(ListNode* pHead1, ListNode* pHead2){
        if(pHead1== nullptr || pHead2 == nullptr)
            return nullptr;
        ListNode* pNode1 = pHead1;
        ListNode* pNode2 = pHead2;
    
        while(pNode1 != pNode2){
            pNode1 = pNode1->next;
            pNode2 = pNode2->next;
            if(pNode1 != pNode2){
                if(pNode1 == nullptr)
                    pNode1 = pHead2;
                if(pNode2 == nullptr)
                    pNode2 = pHead1;
            }
        }
        // 走到最后是pNode1 == pNode2 == nullptr
        // 所以如果有相同的节点,则返回第一个,如果没有,就最后返回nullptr
        return pNode1;
    }
    
  • 相关阅读:
    JZ-C-01
    C/C++学习笔记
    15、排序:选择类排序和归并排序
    玩转Spring——Spring事务
    玩转Spring——Spring整合JDBC
    玩转Spring——Spring AOP
    玩转Spring——Spring IOC/DI
    Java算法——递归思想
    Java排序算法——堆排序
    Java排序算法——归并排序
  • 原文地址:https://www.cnblogs.com/flyingrun/p/13543211.html
Copyright © 2020-2023  润新知