算法 链表 160.链表相交

本文介绍了解决LeetCode160题的算法,即如何使用Java找出两个单链表的相交节点。通过两个指针分别遍历链表,当一个指针到达末尾时移动到另一个链表头部,直到找到相交点或遍历结束。
摘要由CSDN通过智能技术生成


一.题目

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

二.代码

public class LeetCode160 {
    static class ListNode {
        int val;
        ListNode next;

        ListNode(int val) {
            this.val = val;
            this.next = null; // 修改这里,之前的构造函数尝试错误地设置next
        }
    }

    static class Solution160 {
        public ListNode getInterSectionNode(ListNode headA, ListNode headB) {
            if (headA == null || headB == null) {
                return null;
            }
            ListNode a = headA;
            ListNode b = headB;

            while (a != b) {
                a = (a == null) ? headB : a.next;
                b = (b == null) ? headA : b.next;
            }
            return a;
        }
    }

    public static void main(String[] args) {
        // 创建两个相交的链表示例
        // 链表A: 1 -> 2 -> 3
        //                 \
        //                  5 -> 6 -> 7
        //                 /
        // 链表B:    4 -> 5
        ListNode common = new ListNode(5);
        common.next = new ListNode(6);
        common.next.next = new ListNode(7);

        ListNode headA = new ListNode(1);
        headA.next = new ListNode(2);
        headA.next.next = new ListNode(3);
        headA.next.next.next = common;

        ListNode headB = new ListNode(4);
        headB.next = common;

        Solution160 solution160 = new Solution160();
        // 方法调用时去除了类型声明
        ListNode intersectionNode = solution160.getInterSectionNode(headA, headB);
        if (intersectionNode != null) {
            System.out.println("The intersection node's value is " + intersectionNode.val);
        } else {
            System.out.println("No intersection node.");
        }
    }
}

三.总结

三元运算符是一种条件运算符,它包含三个部分,格式为:

条件 ? 表达式1 : 表达式2

其工作原理如下:
条件:这是一个布尔表达式,其结果必须为 true 或 false。
表达式1:如果条件为 true,则计算并返回此表达式的结果。
表达式2:如果条件为 false,则计算并返回此表达式的结果。
三元运算符通常用于简化简单的条件语句,使代码更紧凑。它是 if-else 语句的一种简写形式。例如,考虑以下的 if-else 语句:

java
if (a > b) {
    max = a;
} else {
    max = b;
}

使用三元运算符,上面的代码可以被简化为:

java
max = (a > b) ? a : b;

这两段代码都是用来决定 max 应该被赋值为 a 还是 b,具体取决于 a 是否大于 b。三元运算符因其简洁性而受到欢迎,尤其是在赋值操作和简单逻辑决策中。然而,为了保持代码的可读性,建议在复杂的逻辑判断中使用传统的 if-else 语句,而不是嵌套多个三元运算符。

思路:
为了找到两个单链表相交的起始节点,我们可以使用两个指针分别遍历这两个链表。当一个指针到达链表末尾时,将它移到另一个链表的头部继续遍历;另一个指针也是如此。如果链表相交,那么这两个指针最终会在相交节点处相遇;如果链表不相交,这两个指针最终会同时为 null。

这个方法之所以有效,是因为两个指针会分别遍历两个链表的节点,其遍历的总长度相同,即两个链表的长度之和。这样,如果链表相交,它们就会在相交点相遇;如果不相交,它们会在列表末尾相遇(即都指向 null)。
设想两个链表,A 和 B。它们的长度分别是 a 和 b。假设从链表A的头到相交点的距离是 c,从链表B的头到相交点的距离是 d,相交点到链表末尾的长度为 e。因此,相交的情况下,链表A的长度为 a = c + e,链表B的长度为 b = d + e。

不相交的情形:

如果两个链表不相交,那么遍历完自己的链表后,两个指针分别遍历对方的链表,最终都会到达各自链表的末尾,即 null。这个过程中,每个指针遍历的总长度是 a + b,因此它们会同时到达末尾。
相交的情形:

假设链表相交。指针A开始时位于链表A的头部,指针B位于链表B的头部。
当指针A遍历完链表A(长度为 a)后,它跳到链表B的头部继续遍历;同样,指针B遍历完链表B(长度为 b)后,它跳到链表A的头部继续遍历。
当指针A进入链表B时,它已经遍历了长度 a,接下来它还需要遍历长度 d 才能到达相交点。
当指针B进入链表A时,它已经遍历了长度 b,接下来它还需要遍历长度 c 才能到达相交点。
因此,当指针A和指针B分别遍历了 a + d 和 b + c 后,它们会在相交点相遇。注意到 a + d = b + c(因为 a + d + e = b + c + e,即两个链表的总长度相等),这说明它们会同时到达相交点。
通过这种方式,无论两个链表是否相交,这个算法都能正确地找到相交的起始节点(如果存在的话),或者同时到达链表的末尾(null),表示两个链表不相交。这个方法的巧妙之处在于它利用了遍历长度相同的特性,确保了两个指针能够在相交点相遇,而不需要额外的空间复杂度。

  • 30
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值