Leetcode 160. 相交链表

93 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

1.题目

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

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。

2.思路

本题需要我们找到两个链表相交的起始节点,如何判断两个链表是否相交呢,只需要判断是否有相同的节点并且后续节点都相同,那么从第一个相同节点开始,就是两个链表的相交部分了。

首先我们可以考虑用一个hash表来存储两个链表的节点,首先遍历链表a将里面的节点存入表中,然后遍历链表b对每一个节点判断是否存在于hash表中,如果存在则返回该节点,如果都不存在则说明没有相交节点。

采用hash表虽然能解决这个问题,但是需要额外的存储空间,而我们能不能通过其他方法来节省这个额外的存储空间呢,两条链表判断相交部分需要找到相同的地方,但是由于相交之前的部分并不一定相同,所以我们没法直接判断节点相等。

但是我们可以把链表a接上链表b,链表b接上链表a,这样的情况下,如果相交的话,他们的长度就能保持一致了,我们可以通过双指针的办法,来遍历接入链表,然后判断是否相同,相同则返回当前节点,不同则继续遍历。

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