java实现判断俩个链表是否相交
时间: 2025-03-07 15:14:52 浏览: 35
<think>好的,我现在需要帮助用户了解如何用Java判断两个链表是否相交。首先,我得回想一下链表相交的定义。链表相交指的是两个链表在某个节点之后合并,形成共同的部分。也就是说,从相交节点开始,后续的所有节点都是相同的,直到链表结束。
接下来,我得确定用户的需求。用户可能正在学习数据结构,或者在面试准备中遇到了这个问题。他们需要具体的实现方法,而不仅仅是理论上的解释。因此,我应该提供清晰的思路和代码示例,同时考虑时间和空间复杂度。
首先,我得回顾常见的解决方法。常见的方法有两种:哈希表法和双指针法。哈希表法的思路是遍历第一个链表,将每个节点的引用存入哈希表,然后遍历第二个链表,检查是否有节点存在于哈希表中。这种方法的时间复杂度是O(m+n),空间复杂度也是O(m+n),其中m和n分别是两个链表的长度。
另一种方法是双指针法,也称为“走尾指针法”。这种方法不需要额外空间,时间复杂度同样是O(m+n)。具体步骤是:首先遍历两个链表,找到各自的尾节点,并记录长度。如果尾节点不同,说明不相交;如果相同,则计算两个链表的长度差,让较长的链表的指针先移动差值步,然后两个指针同时移动,直到相遇,相遇点即为相交节点。
用户可能更倾向于高效的方法,尤其是空间复杂度低的解决方案。因此,我应该重点解释双指针法,因为它更优。同时,我需要考虑链表可能存在的环的情况,但通常在这种情况下,题目假设链表无环,所以可能不需要处理环的问题,但最好在注意事项中提及。
然后,我需要考虑如何用Java实现双指针法。首先,定义链表节点的结构,通常是一个包含数据和next指针的类。然后,编写函数来检查相交。具体步骤包括遍历链表获取长度和尾节点,比较尾节点是否相同,调整指针起点,同步遍历直到找到相同节点。
在代码实现中,需要注意边界情况,例如其中一个链表为空,或者两个链表长度相差较大。此外,测试用例的构造也很重要,例如创建相交的链表和不相交的链表来验证代码的正确性。
可能用户还会有疑问,比如如何处理有环的情况,或者是否有其他方法。虽然问题通常假设链表无环,但可以简要说明如果有环的话需要先检测环,然后再处理相交的问题,但这会增加复杂度。
最后,总结思路和步骤,确保用户能够理解并实现该算法。同时,强调时间和空间复杂度,帮助用户评估不同方法的优劣。</think>---
要判断两个链表是否相交,关键在于找到**相交节点**(两个链表的公共节点)。Java中可通过以下两种方法实现:
---
### 方法一:哈希表法
**核心思路**:遍历链表A,将所有节点存入哈希表,再遍历链表B,检查节点是否存在于哈希表中。
**时间复杂度**:$O(m + n)$,空间复杂度:$O(m)$(m、n为链表长度)
```java
import java.util.HashSet;
public class LinkedListIntersection {
static class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
HashSet<ListNode> visited = new HashSet<>();
// 遍历链表A,存储所有节点
while (headA != null) {
visited.add(headA);
headA = headA.next;
}
// 遍历链表B,检查哈希表
while (headB != null) {
if (visited.contains(headB)) {
return headB;
}
headB = headB.next;
}
return null;
}
}
```
---
### 方法二:双指针法(推荐)
**核心思路**:
1. 若两链表相交,则**尾节点必相同**
2. 计算两链表长度差,对齐起点后同步遍历
**时间复杂度**:$O(m + n)$,空间复杂度:$O(1)$
```java
public class LinkedListIntersection {
static class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
// 计算链表A和B的长度
int lenA = getLength(headA), lenB = getLength(headB);
// 对齐起点:长链表先走差值步
ListNode pA = headA, pB = headB;
if (lenA > lenB) {
for (int i = 0; i < lenA - lenB; i++) pA = pA.next;
} else {
for (int i = 0; i < lenB - lenA; i++) pB = pB.next;
}
// 同步遍历找交点
while (pA != null && pB != null) {
if (pA == pB) return pA;
pA = pA.next;
pB = pB.next;
}
return null;
}
private int getLength(ListNode node) {
int len = 0;
while (node != null) {
len++;
node = node.next;
}
return len;
}
}
```
---
### 方法三:巧妙双指针遍历(无长度计算)
**核心思想**:两指针分别遍历A+B和B+A路径,最终会在交点相遇(若存在)。
```java
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode pA = headA, pB = headB;
// 当pA和pB走过相同路径长度时:
// - 若相交,会在交点相遇
// - 若不相交,最终同时为null退出循环
while (pA != pB) {
pA = (pA == null) ? headB : pA.next;
pB = (pB == null) ? headA : pB.next;
}
return pA;
}
```
---
### 验证相交的关键条件
1. **尾节点相同**:若两链表尾节点不同,则一定不相交
2. **节点引用相同**:判断相交的依据是节点对象地址相同,而非值相等
---
### 测试用例示例
```java
public static void main(String[] args) {
// 构造相交链表
ListNode common = new ListNode(8);
common.next = new ListNode(4);
common.next.next = new ListNode(5);
ListNode headA = new ListNode(4);
headA.next = new ListNode(1);
headA.next.next = common;
ListNode headB = new ListNode(5);
headB.next = new ListNode(6);
headB.next.next = new ListNode(1);
headB.next.next.next = common;
// 调用方法判断
ListNode result = getIntersectionNode(headA, headB);
System.out.println(result != null ? "相交节点值:" + result.val : "不相交");
}
```
---
### 复杂度对比
| 方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
|------------|------------|------------|--------------------|
| 哈希表法 | $O(m+n)$ | $O(m)$ | 需要快速实现 |
| 双指针法 | $O(m+n)$ | $O(1)$ | 内存敏感场景 |
| 路径对齐法 | $O(m+n)$ | $O(1)$ | 代码简洁,无需长度 |
---
### 注意事项
1. 若链表可能有环,需先检测环再判断相交(经典相交问题通常假设无环)
2. 节点值可以重复,判断依据是节点引用地址相同而非值相等
3. 空链表直接返回`null`
阅读全文
相关推荐


















