返回

化繁为简:巧妙解决52. 两个链表的第一个公共节点

前端

迎战LeetCode 52. 两个链表的第一个公共节点

题目

给出两个可能有环或无环的链表,找出它们的第一个公共节点。如果两个链表没有公共节点,返回空。

解法一:前后双指针(数节点)

1. 算法思路

前后双指针其实指的是一个指针先走 n 步,另一个指针再与前一个指针以相同的速度走。用到这个思路的还有 LeetCode 160. 相交链表。

将指针 A 和指针 B 都指向链表的头结点。然后,指针 A 先走 n 步,即让 A = A->next 走 n 次,同时让指针 B 走 m 步,即 B = B->next 走 m 次。

一旦指针 A 走完了 n 步,就让指针 B 开始走。之后,让指针 A 和指针 B 都走相同速度,即 A = A->next 和 B = B->next。如果指针 A 和指针 B 在链表中相遇,则说明链表 A 和链表 B 有公共节点,相遇的点就是公共节点。如果指针 A 和指针 B 走到了链表的末尾都没有相遇,则说明链表 A 和链表 B 没有公共节点。

2. 算法代码实现

def getIntersectionNode(headA, headB):
    """
    :type head1, head1: ListNode
    :rtype: ListNode
    """
    pA = headA
    pB = headB
    while pA != pB:
        pA = headB if pA is None else pA.next
        pB = headA if pB is None else pB.next
    return pA

3. 算法复杂度

时间复杂度:O(n+m),其中 n 为链表 A 的长度,m 为链表 B 的长度。

空间复杂度:O(1),因为我们只需要使用常数个变量。

解法二:哈希表

1. 算法思路

使用哈希表存储链表 A 的所有节点。然后,遍历链表 B,如果当前节点在哈希表中,则返回该节点。否则,将当前节点添加到哈希表中,并继续遍历。

2. 算法代码实现

def getIntersectionNode(headA, headB):
    """
    :type head1, head1: ListNode
    :rtype: ListNode
    """
    seen = set()
    while headA:
        seen.add(headA)
        headA = headA.next
    while headB:
        if headB in seen:
            return headB
        seen.add(headB)
        headB = headB.next
    return None

3. 算法复杂度

时间复杂度:O(n+m),其中 n 为链表 A 的长度,m 为链表 B 的长度。

空间复杂度:O(n),因为我们需要使用哈希表来存储链表 A 的所有节点。