📅  最后修改于: 2023-12-03 14:48:53.421000             🧑  作者: Mango
本套装提供了多种解决两个链表的交点问题的算法。
给定两个单链表,判断它们是否相交并找出它们的交点。
注意:
链表的结构定义如下:
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),并且还可以用来判断链表中是否有环。在实际应用中可根据数据规模和性能要求选择适合的算法。