返回

恋爱数学:求解剑指 Offer 52 两个链表的第一个公共节点

前端

前言:相遇之谜

在计算机的世界里,链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个值和指向下一个节点的指针。在现实生活中,链表可以形象地比作一条项链,其中每个珠子代表一个节点,而珠子之间的串线则代表指向下一个节点的指针。

剑指 Offer 52 是一道经典的链表问题,它了一个浪漫的相遇场景:有两个链表,代表着两个恋人 A 和 B,他们从不同的起点出发,却在某个未知的节点相遇了。我们的任务就是找到这个相遇的节点,也就是他们爱情的起点。

解题思路:数学模型

要解开这个相遇之谜,我们可以借助数学模型。设链表 A 的长度为 m,链表 B 的长度为 n,相遇节点到链表 A 起点的距离为 x,相遇节点到链表 B 起点的距离为 y。

当两个恋人 A 和 B 从各自的起点出发时,他们走过的距离分别为:

距离 A = x + y
距离 B = m - x + y

由于他们相遇在同一个节点,因此这两个距离相等:

x + y = m - x + y

简化方程,得到:

2x = m - n

由此可见,相遇节点到链表 A 起点的距离 x 等于链表 A 和链表 B 长度差的二分之一。

解题步骤:双指针法

有了数学模型的支撑,我们可以采用双指针法来求解问题。具体步骤如下:

  1. 初始化两个指针,指向链表 A 和链表 B 的头节点。
  2. 同时移动两个指针,每次移动一步。
  3. 当两个指针同时到达链表尾部时,说明两个链表没有公共节点。
  4. 否则,当一个指针到达链表尾部时,将其指向另一个链表的头节点。
  5. 继续重复步骤 2-4,直到两个指针相遇。
  6. 相遇时,返回相遇节点,即第一个公共节点。

代码实现

def get_intersection_node(headA, headB):
    if not headA or not headB:
        return None

    len_a, len_b = 0, 0
    cur_a, cur_b = headA, headB

    # 计算链表 A 的长度
    while cur_a:
        len_a += 1
        cur_a = cur_a.next

    # 计算链表 B 的长度
    while cur_b:
        len_b += 1
        cur_b = cur_b.next

    # 移动指针,使其到达同一起点
    cur_a, cur_b = headA, headB
    if len_a > len_b:
        for _ in range(len_a - len_b):
            cur_a = cur_a.next
    else:
        for _ in range(len_b - len_a):
            cur_b = cur_b.next

    # 同时移动两个指针,直到相遇
    while cur_a != cur_b:
        cur_a = cur_a.next
        cur_b = cur_b.next

    # 返回相遇节点
    return cur_a

结语:浪漫的启示

通过解开剑指 Offer 52,我们不仅掌握了求解链表公共节点的方法,更领略了一段浪漫的数学邂逅。就像链表中的两个恋人 A 和 B,即使从不同的起点出发,也会在命运的牵引下相遇相知。而数学,就是这相遇之谜中不可或缺的桥梁,它用严谨的逻辑和优雅的公式,为这段浪漫之旅提供了坚实的基础。