zoukankan      html  css  js  c++  java
  • 剑指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);
        }
    }
    
  • 相关阅读:
    LeetCode 24. Swap Nodes in Pairs (两两交换链表中的节点)
    LeetCode 1041. Robot Bounded In Circle (困于环中的机器人)
    LeetCode 1037. Valid Boomerang (有效的回旋镖)
    LeetCode 1108. Defanging an IP Address (IP 地址无效化)
    LeetCode 704. Binary Search (二分查找)
    LeetCode 744. Find Smallest Letter Greater Than Target (寻找比目标字母大的最小字母)
    LeetCode 852. Peak Index in a Mountain Array (山脉数组的峰顶索引)
    LeetCode 817. Linked List Components (链表组件)
    LeetCode 1019. Next Greater Node In Linked List (链表中的下一个更大节点)
    29. Divide Two Integers
  • 原文地址:https://www.cnblogs.com/fyusac/p/15039489.html
Copyright © 2011-2022 走看看