# 相交链表(160)
# 题目
输入两个链表,找出它们的第一个公共节点。
# 示例
输入:intersectVal = 8
, listA = [4,1,8,4,5]
, listB = [5,0,1,8,4,5]
, skipA = 2
, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为
[4,1,8,4,5]
,链表 B 为[5,0,1,8,4,5]
。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
输入:intersectVal = 2
, listA = [0,9,1,2,4]
, listB = [3,2,4]
, skipA = 3
, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为
[0,9,1,2,4]
,链表 B 为[3,2,4]
。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
输入:intersectVal = 0
, listA = [2,6,4]
, listB = [1,5]
, skipA = 3
, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为
[2,6,4]
,链表 B 为[1,5]
。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。这两个链表不相交,因此返回 null。
# 注意
- 如果两个链表没有交点,返回 null。
- 在返回结果后,两个链表仍须保持原有的结构。
- 可假定整个链表结构中没有循环。
- 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
# 算法
# Map
使用Map
来存储链表A
的每一个节点(map的键存储),然后遍历链表B
的每一个节点,使用map.has()
方法来判断是否在map
中存储了相同的节点,如果有则返回该节点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
export const getIntersectionNode = (headA, headB) => {
const map = new Map();
let nodeA = headA;
while (nodeA) {
map.set(nodeA, true);
nodeA = nodeA.next;
}
let nodeB = headB;
while (nodeB) {
if (map.has(nodeB)) return nodeB;
nodeB = nodeB.next;
}
return null;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 双指针
求出链表A
和B
的长度,如果有空链表返回null
,否则将快指针fast
指向较长的链表,将慢指针slow
指向较短的链表,然后让快指针先走两个链表长度的差的步(使两个指针对齐),然后同时向后移动,如果有公共链表则两指针会指向同一个节点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
export const getIntersectionNode = (headA, headB) => {
let nodeA = headA,
nodeB = headB;
let lengthA = 0,
lengthB = 0;
while (nodeA) {
lengthA++;
nodeA = nodeA.next;
}
while (nodeB) {
lengthB++;
nodeB = nodeB.next;
}
if (!lengthA || !lengthB) return null;
let diff = Math.abs(lengthA - lengthB);
let slow = null,
fast = null;
if (lengthA > lengthB) {
slow = headB;
fast = headA;
} else {
slow = headA;
fast = headB;
}
while (diff--) {
fast = fast.next;
}
while (fast && slow) {
if (fast === slow) return fast;
fast = fast.next;
slow = slow.next;
}
return null;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41