JS链表相交问题

145 阅读2分钟

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

image.png

image.png

image.png

链表的长度不一定相等,也就是说两个链表的交点不一定是在他们所在链表的同一位置。

问题分析:

如果同时分别遍历 A 和 B 链表,去比较是否相交的前提是他们的长度相同。假设反复不停的分别遍历 A 和 B,那么经过 N 次之后定会相交.图解:

ScreenRecorderProject1.gif

但是在图中可以看出一个问题,就是遍历的次数过多, B 表 比 A 表元素少一个,那么 A遍历完一次之后,B遍历到了倒数第二个,那么 A开始重新遍历,B开始遍历到最后一个,当 A遍历到第二个的时候, B开始重新遍历,那么最终他们遍历的下标仅仅差了1个,即

当两个链表都进入第二次遍历时, A 遍历下标为 1, B 遍历下标为 0, 原本一开始遍历的时候都是从0开始的

那么很可能就要遍历多次才能找到相交点,照此方法实现:

**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function(headA, headB) {
        let pA = headA
        let pB = headB
        if (pA === null || pB === null) {
            return null
        }
        while(pA !== pB) {
            pA = pA === null ? headA : pA.next
            pB = pB === null ? headB : pB.next
        }

        return pB
};

执行结果:

image.png

很显然内存消耗实在太大,执行用时也超出了预期。那么其实可以是在遍历方法上进行优化,达到减少遍历的次数。

当A表遍历完了之后,就遍历B表。 B表遍历完了之后立即遍历A表,以此遍历,最多2次遍历即可找到相交点。

图解:

ScreenRecorderProject2.gif

优化后:

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function(headA, headB) {
        let pA = headA
        let pB = headB
        if (pA === null || pB === null) {
            return null
        }
        while(pA !== pB) {
            // 将此处作修改
            pA = pA === null ? headB : pA.next
            pB = pB === null ? headA : pB.next
        }

        return pB
};

结果:

image.png

很明显优化后的执行效率更高!