链表相交
难度:
标签:
题目描述
Given two (singly) linked lists, determine if the two lists intersect. Return the inter secting node. Note that the intersection is defined based on reference, not value. That is, if the kth node of the first linked list is the exact same node (by reference) as the jth node of the second linked list, then they are intersecting.
Example 1:
Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 Output: Reference of the node with value = 8 Input Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,0,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
Example 2:
Input: intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 Output: Reference of the node with value = 2 Input Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [0,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B.
Example 3:
Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 Output: null Input Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values. Explanation: The two lists do not intersect, so return null.
Notes:
- If the two linked lists have no intersection at all, return
null
. - The linked lists must retain their original structure after the function returns.
- You may assume there are no cycles anywhere in the entire linked structure.
- Your code should preferably run in O(n) time and use only O(1) memory.
代码结果
运行时间: 168 ms, 内存: 29.6 MB
// Approach: Using Java 8 Streams is not directly applicable as it doesn't have direct support for linked lists.
// However, we can use iterators or implement custom Spliterators if we want to work with Streams.
// Here, the problem is best solved with the two-pointer technique.
// Thus, we provide a general method outline using Streams for conceptual understanding.
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode a = headA;
ListNode b = headB;
// Using Stream.iterate to traverse the list is not straightforward,
// hence we'll follow the same two-pointer approach as above.
while (a != b) {
a = (a == null) ? headB : a.next;
b = (b == null) ? headA : b.next;
}
return a;
}
}
解释
方法:
这个解法利用了两个指针p和q分别遍历两个链表headA和headB。初始时,p指向headA的头节点,q指向headB的头节点。当p和q不相等时,继续遍历。如果p到达链表A的尾部,则将p重新指向链表B的头节点;同理,如果q到达链表B的尾部,则将q重新指向链表A的头节点。这样调整后,p和q继续前进,直到它们相遇或都变为null。如果它们相遇,则返回相遇的节点,这就是两链表的交点。如果p和q都变为null,说明两个链表不相交,返回null。
时间复杂度:
O(m+n)
空间复杂度:
O(1)
代码细节讲解
🦆
在此解法中,为什么在p或q到达链表末端时,将它们指向另一个链表的头节点有助于找到交点?
▷🦆
此解法中,两个指针最终相遇的节点真的是交点吗,还是有可能是两个链表的尾部null?
▷🦆
在链表不相交的情况下,此算法如何确保最终返回null而不是错误的节点?
▷🦆
此方法是否考虑了所有可能的边界条件,例如一个或两个链表为空的情况?
▷