leetcode
leetcode 2901 ~ 2950
相交链表

相交链表

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 63 ms, 内存: 26.0 MB


/*
 * 题目思路:
 * 使用 Java Stream 不适用于处理链表的这种特定问题,因为链表的遍历需要依赖于节点的指针操作,
 * Stream 更适合处理集合类的数据流操作。但我们可以简单模拟传统方法。
 */

import java.util.HashSet;
import java.util.Set;

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        Set<ListNode> visited = new HashSet<>();

        ListNode current = headA;
        while (current != null) {
            visited.add(current);
            current = current.next;
        }

        current = headB;
        while (current != null) {
            if (visited.contains(current)) {
                return current;
            }
            current = current.next;
        }

        return null;
    }
}

解释

方法:

此题解采用了双指针的方法。两个指针分别指向两个链表的头节点,然后依次向后遍历。当一个指针到达链表末尾时,将其指向另一个链表的头节点继续遍历。这样,两个指针会在第二次遍历时同时到达相交节点或者都到达末尾(不相交的情况)。这个方法利用了一个事实:两个链表的头节点到相交节点的距离差等于两个链表的长度差。

时间复杂度:

O(m+n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在指针到达链表末尾时,需要将其重新指向另一个链表的头节点,这样做的目的是什么?
这种做法是为了消除两个链表在长度上的差异。假设链表A的长度为a,链表B的长度为b,假设a < b。当使用两个指针分别从两个链表的头部开始遍历时,指向A的指针会先到达A的末尾。此时,将它指向B的头部开始遍历,而指向B的指针稍后到达B的末尾,然后指向A的头部。这样调整后,两个指针会分别走过长度为b + a,确保了即使两个链表长度不同,它们也能在第二次遍历中有同样的起点,从而有机会在某一点相遇,该点即为两链表的相交点,如果存在的话。
🦆
如果链表相交,双指针在什么情况下会同时到达相交节点?
如果链表相交,双指针会在第二次遍历中同时到达相交节点。这是因为在第一次遍历中,两个指针虽然以不同的速度到达各自链表的末尾,但在开始第二次遍历时,它们交换了起始链表,从而消除了任何长度差异。因此,当两个链表相交时,它们将以相同的步数前进到相交点,从而同时到达该交点。
🦆
在没有相交点的情况下,双指针最终会停在什么位置?
在没有相交点的情况下,双指针最终会同时达到两个链表的末尾并且都指向None。这是因为,即使两个链表长度不同,通过交换起始链表的方式,两个指针都会遍历完整个链表A和链表B的长度(总共走过a + b的长度),如果没有相交点,它们将同时到达链表的末尾,即None。

相关问题