剑指 Offer 52. 两个链表的第一个公共节点

Posted 炫云云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 52. 两个链表的第一个公共节点相关的知识,希望对你有一定的参考价值。

剑指 Offer 52. 两个链表的第一个公共节点

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

如下面的两个链表**:**

在节点 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 = 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。

双指针

使用双指针的方法,可以将空间复杂度降至 O ( 1 ) O(1) O(1)

只有当链表 head A A A h e a d B h e a d B headB 都不为空时,两个链表才可能相交。因此首先判断链表 h e a d A h e a d A headA 和 head B B B 是否为空, 如果其中至少有一个链表为空,则两个链表一定不相交,返回 null。

当链表 head A A A h e a d B h e a d B headB 都不为空时,创建两个指针 p A p A pA p B p B pB, 初始时分别指向两个链表的头节点 head A A A h e a d B h e a d B headB​, 然后将两个指针依次谝历两个链表的每个节点。具体做法如下:

  • 每步操作需要同时更新指针 p A p A pA p B 。  p B_{\\text {。 }} pB 
  • 如果指针 p A p A pA 不为空,则将指针 p A p A pA 移到下一个节点; 如果指针 p B p B pB 不为空,则将指针 p B p B pB 移到 下一个节点。
  • 如果指针 p A p A pA 为空,则将指针 p A p A pA 移到链表 h e a d B h e a d B headB 的头节点; 如果指针 p B p B pB 为空,则将指针 p B p B pB 移到链表 h e a d A h e a d A headA 的头节点。
  • 当指针 p A p A pA p B p B pB 指向同一个节点或者都为空时,返回它们指向的节点或者 null。

证明

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        if not headA or not headB:
            return None
        curA,curB = headA,headB
        while curA !=curB:
            curA = curA.next if curA else headB
            curB = curB.next if curB else headA
        return curA

差值解法

先对两条链表扫描一遍,取得两者长度,然后让长的链表先走「两者的长度差值」,然后再同时走,遇到第一个节点即是答案。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        def length(L):
            n = 0
            while L:
                n += 1; L = L.next
            return n 
        len1, len2 = length(headA), length(headB)
        if len1 > len2:
            headA, headB = headB, headA
        for _ in range(abs(len1 - len2)):
            headB = headB.next
        while headA and headB and headA is not headB:
            headA, headB = headA.next, headB.next
        return headA

参考

Krahets - 力扣(LeetCode) (leetcode-cn.com)

以上是关于剑指 Offer 52. 两个链表的第一个公共节点的主要内容,如果未能解决你的问题,请参考以下文章

[8月4日]剑指 Offer 52. 两个链表的第一个公共节点

剑指 Offer 52-两个链表的第一个公共节点

剑指 Offer 52. 两个链表的第一个公共节点

剑指 Offer 52. 两个链表的第一个公共节点

算法剑指 Offer 52. 两个链表的第一个公共节点

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