力扣题目——160. 相交链表

注:本文的代码实现使用的是 JS(JavaScript),为前端中想使用JS练习算法和数据结构的小伙伴提供解题思路。

描述

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。题目数据保证整个链式结构中不存在环。

图示两个链表在节点 c1 开始相交:
在这里插入图片描述
注意,函数返回结果后,链表必须保持其原始结构 。


示例:

在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

提示:

  • listA 中节点数目为 m
  • listB 中节点数目为 n
  • 0 <= m, n <= 3 * 104
  • 1 <= Node.val <= 105
  • 0 <= skipA <= m
  • 0 <= skipB <= n
  • 如果 listA 和 listB 没有交点,intersectVal 为 0
  • 如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]

解题思路

哈希法

创建一个哈希表,然后依次存放其中一个链表的所有节点。随后遍历另一个链表,遍历的时候判断当前节点是否在哈希表中出现过,若出现,则为交点,若遍历结束,则返回null

var getIntersectionNode = function(headA, headB) {
    let setA = new Set()
    let pA = headA
    let pB = headB
    // 将 A 链表中的每个节点都放到集合中
    while(pA){
        setA.add(pA)
        pA = pA.next
    }
    // 检测 B 中的节点是否曾经在 A 中出现
    while(pB){
        if(setA.has(pB)) return pB
        pB = pB.next
    }
    return null
};

双指针法

记A独有的节点数为a,B独有的节点数为b ,交点及其之后的节点数为c(即A和B共享的节点)。
我们可以使用两个指针,分别指向A和B,依次遍历,遍历完自己的节点后遍历对方的节点。若某个时刻两个指针所指向的节点相同,则存在相交节点。

举例:假设相交节点存在。初始指向链表A 的指针为pA,遍历完后,走了a+c步,此时将pA指向链表B的头节点,若想pA走到交点,需要再走b步,累计走过了a+c+b步;同理,始指向链表B 的指针为pB,遍历完后,走了b+c步,此时将pB指向链表A的头节点,若想pB走到交点,需要再走a步,需要走过b+c+a步,此时正好步数一样。

var getIntersectionNode = function(headA, headB) {
    if(!headA || !headB) return null
    let pA = headA, pB = headB
    while(pA !== pB){
        pA = pA === null ? headB : pA.next
        pB = pB === null ? headA : pB.next
    }
    return pA
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值