前端算法-链表相交

122 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

题目

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

输入: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出: null
解释: 从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。

思路一

我们可以使用双指针方法,进去先判断当前的形参headA和headB其中一个值是否为null,如果其中一个值为null则直接返回null,两个指针同时遍历两个链表,每个指针遍历两个链表各一次,当pA遍历链表A结束时,再指向链表B头结点,否则继续遍历链表A,当pB遍历链表B结束时,再指向链表A头节点;否则继续遍历链表B,pA和pB相遇的地方即为相交点,最后返回即可

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

思路二

我们这里已知如果两个链表有交点,那么一定是后一小截相同, 所以将两个链表的起点统一即可,dist变量用来记录两个链表的长度差,lengthA和lengthB变量用来记录长度,p1和p2变量用来记录表头,在遍历完链表取得长度后在重新指回表头,获取headA和headB的长度,并重新指回表头,在进行较长链表的指针移位操作,从相同后缀的长度开始遍历链表,找到相同链表节点,最后将其返回即可

var getIntersectionNode = function(headA, headB) {
    let dist = 0;
    let lengthA = 0, lengthB = 0
    let p1 = headA, p2 = headB;
    while (headA) {
        lengthA++;
        headA = headA.next;
    }
    while (headB) {
        lengthB++;
        headB = headB.next;
    }
    headA = p1;
    headB = p2;
    if (lengthA < lengthB) {
        dist = lengthB - lengthA;
        while (dist--) {
            headB = headB.next;
        }
    } else if (lengthA > lengthB) {
        dist = lengthA - lengthB;
        while (dist--) {
            headA = headA.next;
        }
    }
    while (headA && headB) {
        if (headA === headB) {
            return headB;
        }
        headA = headA.next;
        headB = headB.next;
    }
    return null;
};