160.相交链表
160. 相交链表
题目
给你两个单链表的头节点 headA 和 headB,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null。
图示两个链表在节点 c1 开始相交:

题目数据保证整个链式结构中不存在环。
注意,函数返回结果后,链表必须保持其原始结构。
示例 1:
输入: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出: Intersected at '8'
解释: 相交节点的值为 8。
示例 2:
输入: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出: Intersected at '2'
示例 3:
输入: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出: null
解释: 两个链表不相交。
提示
listA中节点数目为mlistB中节点数目为n1 <= m, n <= 3 * 10^41 <= Node.val <= 10^50 <= skipA <= m0 <= skipB <= n- 如果
listA和listB没有交点,intersectVal为0 - 如果
listA和listB有交点,intersectVal == listA[skipA] == listB[skipB]
进阶
你能否设计一个时间复杂度 $O(m + n)$、仅用 $O(1)$ 内存的解决方案?
解法
解法一:暴力枚举
因为我比较菜,一开始采用了双重循环,遍历两个链表的所有节点组合,判断是否为同一节点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* getIntersectionNode(struct ListNode* headA,
struct ListNode* headB) {
struct ListNode* listA = headA;
while (listA != NULL) {
struct ListNode* listB = headB;
while (listB != NULL) {
if (listA == listB) {
return listA;
}
listB = listB->next;
}
listA = listA->next;
}
return NULL;
}
复杂度分析
- 时间复杂度:$O(m \times n)$,其中 $m$ 和 $n$ 分别为两个链表的长度。双重循环导致最坏情况下需要遍历所有节点组合,在 LeetCode 上会超时。
- 空间复杂度:$O(1)$,只使用了常数额外空间。
解法二:双指针(双链表遍历)
这个解法是从网上搜到的,核心思想是使两个指针走过的距离相同。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* getIntersectionNode(struct ListNode* headA,
struct ListNode* headB) {
if (headA == NULL || headB == NULL) return NULL;
struct ListNode* listA = headA;
struct ListNode* listB = headB;
while (listA != listB) {
listA = (listA == NULL) ? headB : listA->next;
listB = (listB == NULL) ? headA : listB->next;
}
return listA;
}
原理分析
设链表 A 的长度为 $m$,链表 B 的长度为 $n$,相交部分的长度为 $c$。
- 指针
listA遍历完链表A(共 $m$ 步)后转向headB,继续走 $n - c$ 步到达交点,总步数为 $m + (n - c)$。 - 指针
listB遍历完链表B(共 $n$ 步)后转向headA,继续走 $m - c$ 步到达交点,总步数为 $n + (m - c)$。
两者总步数相等(均为 $m + n - c$),因此会在交点相遇。若两个链表不相交($c = 0$),则两个指针最终都会走向 NULL,此时 listA == listB == NULL,循环结束,返回 NULL。
复杂度分析
- 时间复杂度:$O(m + n)$,每个指针最多遍历 $m + n$ 个节点。
- 空间复杂度:$O(1)$,只使用了常数额外空间。

浙公网安备 33010602011771号