LeetCode 面试题 02.07. 链表相交

题目:

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

图示两个链表在节点 c1 开始相交img

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

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

示例 1:

img

输入: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 个节点。

思路/代码

这道题目相对来说是比较简单的了,但是本人还是没有想出来第二种方法,只能说双指针YYDS,而且还需要对两个指针遍历的数量关系有一定的了解

这题就是利用了链表A和B的长度数量关系和指针遍历的特性进行解题的

方法一:哈希表

哈希集合对大家来说应该不会陌生,Set集合中有一个方法contains()可以获取集合中是否存在指定的元素,我们可以先遍历链表A,将链表中的所有元素存入Set集合中,由于题目告诉我们了,相交链表没有环,所以我们可以使用P指针直接遍历B链表,然后对B链表中每个元素使用contains()方法判断是否存在于Set集合中,存在就直接返回,当P指针为NULL的时候代表A和B链表不相交

具体代码:

public ListNode setMethod(ListNode headA,ListNode headB) {
    Set<ListNode> set = new HashSet();
    
    //将A链表元素存入集合中
    while(headA != null) {
        set.add(headA);
        headA = headA.next;
    }
    
    //遍历B链表判断是否存在于集合中
    while(headB != null) {
        if(set.contains(headB)){
            return headB;
        }
        headB = headB.next;
    }
    //没有找到交点
    return null;
}

方法二:双指针

接下来就是十分优雅的双指针解法了、看到这个解法真的是秀了我一脸

具体思路就是定义两个指针P1和P2,让P1和P2分别同时向后移动,链表会有两种情况

  1. 两个链表有交点

    我们可以假设链表A长度为m,链表B长度为n,链表A不相交的长度为a,链表B不相交长度为b,两个链表相交部分长度为c

    • 当a等于b的时候,我们的P1和P2指针应该是可以同时移动到一个相等节点的,这个时候直接返回P1指针指向的元素即可

    • 当a不等于b的时候 P1指针应该移动a + c + b才能到达相交的位置,P2指针应该移动b + c + a才能到达相交的位置

      由于 a + c + b = b + c + a 所以当P1指针先到达NULL的时候让其指向B链表,当P2指针到达NULL让其指向A链表,并且继续向后移动,直到P1 = P2就可以返回P1

  2. 两个链表无交点

    • 当a 不等于 b时候,P1移动m+n,P2移动n+m的时候相等,而且都等于NULL

    • 当a 等于 b的时候,P1移动m,P2移动n的时候相等,而且都为NULL

public ListNode setMethod(ListNode headA,ListNode headB) {
    //如果A或者B链表有一个为NULL就不可能有交点
    if(headA == null || headB == null) {
        return null;
    }
    
    //定义两个指针
    ListNode p1 = headA;
    ListNode p2 = headB;
    while(p1 != p2) {
        p1 = p1 == null ? headB : p1.next;
        p2 = p2 == null ? headA : p2.next;
    }
    //不管如何都返回p1,因为最后不是相交节点就是NULL
    return p1;
}

总结

这道题目其实更多考察的是思维上的模式,代码并不难,我们要学会对问题进行抽象,并且分析问题中的关键对象和数量关系,只有看懂了题目才能有思路,有了思路,解题就能更加得心应手!

共勉!

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨白Coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值