LeetCode hot 100 每日一题(17)——160.相交链表
这是一道难度为简单的题目,让我们来看看题目描述:
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
提示:
- listA 中节点数目为 m
- listB 中节点数目为 n
- 1 <= m, n <= 3 * 1 0 4 10^4 104
- 1 <= Node.val <= 1 0 5 10^5 105
- 0 <= skipA <= m
- 0 <= skipB <= n
- 如果 listA 和 listB 没有交点,intersectVal 为 0
- 如果 listA 和 listB 有交点,intersectVal == listA[skipA] == listB[skipB]
题解
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// 定义两个指针,分别指向两个链表的头节点
ListNode p = headA;
ListNode q = headB;
// 当两个指针不相等时持续遍历
while(p != q){
// 如果 p 到达链表 A 的末尾,则将其重定向到链表 B 的头部
if(p == null){
p = headB;
} else {
// 否则继续向下遍历链表 A
p = p.next;
}
// 如果 q 到达链表 B 的末尾,则将其重定向到链表 A 的头部
if(q == null){
q = headA;
} else {
// 否则继续向下遍历链表 B
q = q.next;
}
}
// 最终 p 和 q 要么在交点处相遇,要么都为 null(表示没有交点)
return p;
}
}
具体算法如下:
- 初始化两个指针 p=headA, q=headB。
- 不断循环,直到 p=q。
- 每次循环,p 和 q 各向后走一步。具体来说,如果 p 不是空节点,那么更新 p 为 p.next,否则更新 p 为 headB;如果 q 不是空节点,那么更新 q 为 q.next,否则更新 q 为 headA。
- 循环结束时,如果两条链表相交,那么此时 p 和 q 都在相交的起始节点处,返回 p;如果两条链表不相交,那么 p 和 q 都走到空节点,所以也可以返回 p,即空节点。
假设第一条链表长度为
x
+
z
x+z
x+z
假设第一条链表长度为
y
+
z
y+z
y+z
其中
z
z
z 是两条链表的公共部分长度
注意:为了兼容没有交点的情况,把空节点也算进来
这样的解法保证两个指针走了一样的长度为
x
+
y
+
z
x+y+z
x+y+z
复杂度分析
时间复杂度:O(m + n),其中 m 和 n 分别为两个链表的长度
空间复杂度:O(1),只用了两个指针,没有额外空间开销
参考
灵神题解