📜  两个链表的交点|套装3(1)

📅  最后修改于: 2023-12-03 14:48:53.421000             🧑  作者: Mango

两个链表的交点|套装3

本套装提供了多种解决两个链表的交点问题的算法。

题目描述

给定两个单链表,判断它们是否相交并找出它们的交点。

注意:

  • 如果两个链表没有交点,返回 null.
  • 在返回结果后,两个链表仍须保持原有的结构。
  • 可假定整个链表结构中没有循环。
  • 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

链表的结构定义如下:

public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}
解法一:哈希表

将其中一个链表的所有节点存入哈希表中,然后遍历另一个链表,查找是否在哈希表中出现过相同节点,如果有,则说明两个链表相交,返回这个节点即可。

时间复杂度为 O(m+n),空间复杂度为 O(m) 或 O(n),取决于哪个链表更长。

Java 代码实现:

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) { // 如果有一个链表为空,则一定不相交
        return null;
    }
    Set<ListNode> set = new HashSet<>();
    ListNode curA = headA;
    while (curA != null) { // 将链表 headA 中的所有节点存入哈希表中
        set.add(curA);
        curA = curA.next;
    }
    ListNode curB = headB;
    while (curB != null) { // 遍历链表 headB,查找是否在哈希表中出现过相同节点
        if (set.contains(curB)) {
            return curB;
        }
        curB = curB.next;
    }
    return null; // 如果两个链表不相交,会在这里返回 null
}
解法二:双指针

假设链表 A 的长度为 a,链表 B 的长度为 b,两个链表的共同部分长度为 c,如下图所示:

A:a1 → a2 → a3 → → → ac → → → xa(m-c+1) → xa(m-c+2) → → → xam → null
B:b1 → b2 → b3 → → → bc → → → xb(n-c+1) → xb(n-c+2) → → → xbn → null

可以发现,如果两个链表相交,那么它们尾部的节点一定是共同的,如上图中的 xa(m-c+1) 和 xb(n-c+1)。如果我们从尾部开始向前遍历两个链表,直到找到第一个不相等的节点,那么这个节点的下一个节点就是它们的交点。

由于两个链表的长度不一定相等,所以我们分别从链表 A 和链表 B 的头节点开始向尾节点遍历,如果到达尾部就从另一个链表的头节点开始遍历,直到遍历到相同的节点,如果没有相同的节点,则两个链表不相交。

时间复杂度为 O(m+n),空间复杂度为 O(1)。

Java 代码实现:

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) { // 如果有一个链表为空,则一定不相交
        return null;
    }
    ListNode curA = headA;
    ListNode curB = headB;
    while (curA != curB) {
        curA = (curA != null) ? curA.next : headB; // 遍历链表 A
        curB = (curB != null) ? curB.next : headA; // 遍历链表 B
    }
    return curA; // 返回相交的节点,如果不相交会在循环结束后返回 null
}
总结

本套装提供了两种解决两个链表的交点问题的算法,其中哈希表需要额外的空间来存储节点,时间复杂度为 O(m+n);而双指针方法不需要额外的空间,时间复杂度为 O(m+n),并且还可以用来判断链表中是否有环。在实际应用中可根据数据规模和性能要求选择适合的算法。