• 剑指offer52 两个链表的第一个公共节点


    输入两个链表,找出它们的第一个公共节点。

    如下面的两个链表

    在节点 c1 开始相交。

    示例 1:

    输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
    输出:Reference of the node with value = 8
    输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
    

    示例 2:

    输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
    输出:Reference of the node with value = 2
    输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
    

    示例 3:

    输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
    输出:null
    输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
    解释:这两个链表不相交,因此返回 null。
    
    • 如果两个链表没有交点,返回 null.
    • 在返回结果后,两个链表仍须保持原有的结构。
    • 可假定整个链表结构中没有循环。
    • 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

    双指针

    方法1:先遍历两个长度,然后先遍历长的,距离为两个链表长度之差,然后对两个链表同时遍历

    /**
     * 方法1:先遍历两个长度,然后先遍历长的,距离为两个链表长度之差,然后对两个链表同时遍历
     *
     * @param headA
     * @param headB
     * @return
     */
    public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) return null;
    
        ListNode pA = headA;
        int cntA = 0;
        while (pA != null) {
            pA = pA.next;
            cntA++;
        }
        ListNode pB = headB;
        int cntB = 0;
        while (pB != null) {
            pB = pB.next;
            cntB++;
        }
    
        ListNode listNodeF = cntA >= cntB ? headA : headB;
        ListNode listNodeS = cntA >= cntB ? headB : headA;
        int len = cntA >= cntB ? cntA - cntB : cntB - cntA;
        while (len > 0 && listNodeF != null) {
            len--;
            listNodeF = listNodeF.next;
        }
        // 两指针可以同时指向同一节点,包括null,也有可能其一指向null,另一个不指向null
        while (listNodeS != null || listNodeF != null) {
            if (listNodeF == listNodeS) return listNodeF;
            listNodeF = listNodeF.next;
            listNodeS = listNodeS.next;
        }
        return null;
    }
    

    方法2:双指针同时遍历两个链表,如果遍历到为空,则指向另一个链表,相遇位置即为第一个公共节点

    /**
     * 方法2:双指针同时遍历两个链表,如果遍历到为空,则指向另一个链表,相遇位置即为第一个公共节点
     *
     * @param headA
     * @param headB
     * @return
     */
    public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) return null;
    
        ListNode listNodeP = headA;
        ListNode listNodeQ = headB;
        while (listNodeP != listNodeQ) {
            listNodeP = listNodeP != null ? listNodeP.next : headB;
            listNodeQ = listNodeQ != null ? listNodeQ.next : headA;
        }
        return listNodeP;
    }
    

    测试用例

    public static void main(String[] args) {
        // listA=[0,9,1,2,4],listB = [3,2,4],
        ListNode headA = new ListNode(0);
        ListNode headA2 = new ListNode(9);
        headA.next = headA2;
        ListNode headA3 = new ListNode(1);
        headA2.next = headA3;
        ListNode headA4 = new ListNode(2);
        headA3.next = headA4;
        ListNode headA5 = new ListNode(4);
        headA4.next = headA5;
    
        ListNode headB = new ListNode(3);
        headB.next = headA4;
    
        ListNode listNode = getIntersectionNode(headA, headB);
        if (listNode != null) {
            System.out.println("GetIntersectionNode52 demo01 result:" + listNode.val);
        }
    
        // listA = [4,1,8,4,5], listB = [5,0,1,8,4,5],
        headA = new ListNode(4);
        headA2 = new ListNode(1);
        headA.next = headA2;
        headA3 = new ListNode(8);
        headA2.next = headA3;
        headA4 = new ListNode(4);
        headA3.next = headA4;
        headA5 = new ListNode(5);
        headA4.next = headA5;
    
        headB = new ListNode(5);
        ListNode headB2 = new ListNode(0);
        headB.next = headB2;
        ListNode headB3 = new ListNode(1);
        headB2.next = headB3;
        headB3.next = headA3;
        listNode = getIntersectionNode(headA, headB);
        if (listNode != null) {
            System.out.println("GetIntersectionNode52 demo02 result:" + listNode.val);
        }
    }
    
  • 相关阅读:
    难道真的是RedBook错了?
    用一个土办法证明RedBook的错误
    Md5 Loader Demo
    simple shadow mapping
    又遇到让人疑惑的问题
    [洛谷P1037][题解]产生数
    [洛谷P1279][题解]字串距离
    [洛谷P1122][题解]最大子树和
    [洛谷P1144][题解]最短路计数
    Vue 之 Data
  • 原文地址:https://www.cnblogs.com/fyusac/p/15039489.html
Copyright © 2020-2023  润新知