LeetCode 160. 相交链表 双指针哈希表详解 Java实现

160. 相交链表

题目来源

160. 相交链表

题目分析

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

题目难度

  • 难度:简单

题目标签

  • 标签:链表、双指针

题目限制

  • 两个链表中不存在环。
  • headAheadB 的长度分别为 mn
  • 0 <= m, n <= 3 * 10^4
  • 1 <= Node.val <= 10^5

解题思路

思路:双指针法

  1. 问题定义

    • 要求找到两个单链表相交的起始节点。通过遍历两个链表,判断它们的相同节点。
  2. 核心算法

    • 双指针法:使用两个指针分别遍历两个链表,当一个指针到达链表尾部时,跳转到另一个链表的头部继续遍历。这样两个指针最终会在相交点相遇或同时到达 null
  3. 关键步骤

    • 初始化两个指针 pApB,分别指向 headAheadB
    • 遍历两个链表,当 pA 到达链表尾部时跳转到 headBpB 到达链表尾部时跳转到 headA
    • 如果两个指针相遇,返回该节点;如果两个指针同时到达 null,则返回 null

核心算法步骤

  1. 初始化指针

    • 将两个指针分别初始化为 headAheadB
  2. 遍历链表

    • 当两个指针不相等时,继续遍历。如果其中一个指针到达 null,则将其跳转到另一个链表的头部。
  3. 返回结果

    • 当两个指针相遇时,返回该节点;如果两个指针都为 null,则返回 null

代码实现

以下是双指针法的 Java 代码实现:

/**
 * 160. 相交链表
 * @param headA 链表1
 * @param headB 链表2
 * @return 相交的起始节点
 * @apiNote 双指针法,时间复杂度O(m+n),空间复杂度O(1)
 */
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) {
        return null;
    }
    ListNode pA = headA;
    ListNode pB = headB;
    while (pA != pB) {
        pA = pA == null ? headB : pA.next;
        pB = pB == null ? headA : pB.next;
    }
    return pA;
}

代码解读

  • 双指针遍历pApB 分别遍历 headAheadB,当一个指针到达 null 时,切换到另一个链表的头部。
  • 判断相交节点:当 pApB 相遇时,返回相交节点;否则返回 null

性能分析

  • 时间复杂度O(m + n),其中 mn 分别是两个链表的长度。每个指针最多遍历两个链表的总长度。
  • 空间复杂度O(1),只使用了常量级的额外空间。

测试用例

你可以使用以下测试用例来验证代码的正确性:

// 测试用例1
ListNode headA1 = new ListNode(4);
ListNode headB1 = new ListNode(5);
ListNode common1 = new ListNode(8);
headA1.next = new ListNode(1, common1);
headB1.next = new ListNode(6, new ListNode(1, common1));
common1.next = new ListNode(4, new ListNode(5));
ListNode result1 = getIntersectionNode(headA1, headB1);
System.out.println(result1.val); // 输出: 8

// 测试用例2
ListNode headA2 = new ListNode(2, new ListNode(6, new ListNode(4)));
ListNode headB2 = new ListNode(1, new ListNode(5));
ListNode result2 = getIntersectionNode(headA2, headB2);
System.out.println(result2); // 输出: null

扩展讨论

其他实现

  • 长度对齐法:通过计算两个链表的长度,让较长的链表先遍历一定距离以对齐两个链表的长度,然后同时遍历两个链表,找到相交节点。
  • 哈希表法:使用哈希表记录 headA 中的节点,再遍历 headB,找到第一个在哈希表中的节点即为相交节点。
// 哈希
        Map<ListNode,Integer> map=new HashMap<>();
        ListNode p=headA;
        while(p!=null){
            map.merge(p,1,Integer::sum);
            p=p.next;
        }
        p=headB;
        while(p!=null){
            map.merge(p,1,Integer::sum);
            if(map.get(p)>1){
                return p;
            }
            p=p.next;
        }
        return null;

总结

这道题目考察了链表的相交问题,双指针法通过简单有效的遍历,能够在 O(m + n) 的时间复杂度内找到相交节点或确认两个链表不相交。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值