22.相交链表

55 阅读2分钟

题目链接

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

解法1 暴力解法

思路

最暴力的解法就是遍历A链表同时逐个遍历B链表,如果相同则返回。

如果A走到最后则没有相交,则返回null节点。

代码

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
    let currentA = headA;
    while (currentA !== null) {
        let currentB = headB;
        while (currentB !== null) {
            if (currentA === currentB) {
                return currentA;
            }
            currentB = currentB.next;
        }
        currentA = currentA.next;
    }
    return null;
};

时空复杂度分析

时间复杂度:两层遍历,O(m * n)。该方法可以AC

空间复杂度:O(1)

题解2 哈希表缓存

思路

两层遍历时间复杂度过于高,我们可以利用空间缓存。

先遍历A链表用哈希表缓存下来,接下来遍历B链表逐个查询是否存在即可找到答案。

代码

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
    let current = headA;
    const hashSet = new Set();
    while (current) {
        hashSet.add(current);
        current = current.next;
    }
    current = headB;
    while (current) {
        if (hashSet.has(current)) {
            return current;
        }
        current = current.next;
    }
    return null;
};

时空复杂度分析

时间复杂度:两次遍历,O(m + n)

空间复杂度:使用哈希表缓存A链表,O(m)

解法3 双指针

思路

我们可以用两个指针,一个从A链表出发,如果走到链表末尾,则从B链表头重新出发。

另一个指针则相反,从B链表头出发,走到末尾再从A链表头出发。

如果有交点,则都走了 i + j + k 段,节点数相同。

image.png

如果没有交点,则都走了 i + j 段。最后走到队尾 null 节点。

image.png

代码

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
    let currentA = headA;
    let currentB = headB;

    while (currentA !== currentB) {
        currentA = currentA === null ? headB : currentA.next;
        currentB = currentB === null ? headA : currentB.next;
    }
    return currentA;
};

时空复杂度分析

时间复杂度:O(m + n)

空间复杂度:O(1)