leetcode160.相交链表

一.题目描述

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

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

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

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

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

提示:

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]

进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?

二.题目解析

1.消除长度差

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        /*因为两个链表相交部分往后的节点都相同,所以若长度不相同则多余的长度一定在前面
        1->2->3->4->5
     1->2->6->3->4->5
     时间复杂度O(m+n),空间复杂度O(1)
        * */
        ListNode p1 = headA,p2 = headB;
        int count1 = 0,count2 = 0;
        //获取到两个链表各自的长度
        while (p1 != null){
            count1++;
            p1 = p1.next;
        }
        while (p2 != null){
            count2++;
            p2 = p2.next;
        }
        p1 = headA;
        p2 = headB;
        int diff = count1 - count2;
        int abs = Math.abs(diff);
        //指向长度较长的那个链表的指针先走多余的步数
        if(diff != 0){
            while (abs > 0){
                p1 = diff < 0 ? p1 : p1.next;
                p2 = diff > 0 ? p2 : p2.next;
                abs--;
            }
        }
        //两个指针同时开始走
        while (p1 != null && p2 != null){
            if(p1 == p2){
                return p1;
            }
            p1 = p1.next;
            p2 = p2.next;
        }
        return null;
    }

在这里插入图片描述
2.消除长度差另一种方式

public ListNode getIntersectionNode1(ListNode headA, ListNode headB) {
        /*也是利用了两链表长度差,时间复杂度O(m+n)(最差情况下无公共节点,需要遍历m+n个节点),空间复杂度O(1)
        当原较长链表的指针指向较短链表的head时,原较短链表的指针指向较长链表的head+长度差的距离,
        也就消除了"长度差"的影响,此时两指针一起向前遍历即可
        * */
        ListNode p1 = headA,p2 = headB;
        while (p1 != p2){
            p1 = p1 == null ? headB : p1.next;
            p2 = p2 == null ? headA : p2.next;
        }
        //有公共节点则返回这个公共节点,无公共节点则都指向的是null,也是返回p1即可
        return p1;
    }

在这里插入图片描述
3.造环,问题转化为求环入口

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。
public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
        /*造环,将A链首尾相连,若A、B有交点,即相当于B链有环,转化为求B链环口位置
        时间复杂度O(m+n),空间复杂度O(1)
        * */
        ListNode p1 = headA,p2 = headB;
        while (p1.next != null){
            p1 = p1.next;
        }
        //将A链表首尾相连
        p1.next = headA;
        //快慢指针同时指向headB,寻找环入口
        ListNode fast = headB,slow = headB;
        while (fast != null && fast.next != null){
            //快慢指针按照不同的速度移动
            fast = fast.next.next;
            slow = slow.next;
            //此时在环内相遇
            if(fast == slow){
                //fast指针指向起点
                fast = headB;
                //fast指针和slow指针到环口等距离,两指针同时向前走即可同步到达环入口
                while (fast != slow){
                    fast = fast.next;
                    slow = slow.next;
                }
                //取消A链表的首尾相连
                p1.next = null;
                return fast;
            }
        }
        //取消A链表的首尾相连
        p1.next = null;
        return null;

    }

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值