160. 相交链表
这虽然是道简单题,但是最简单的方法(Set数组存一边然后另一边遍历判断当前结点是否存在于另一边)性能很一般,可以思考用双指针来优化写法(可以将空间复杂度降至 O(1))
捋思路时,要分情况去讨论。
做算法题记得先判空,不为空才有是否相交可讨论。
- 有相交,长度相等
- 有相交,长度不相等
- 无相交,长度相等
- 无相交,长度不相等
设链表 headA 和 headB 长度分别设为 m 和 n。
1.两个链表相交
设headA 的不相交部分有 a 个节点, headB 的不相交部分有 b 个节点,两链表相交部分有 c 个节点。👇👇
则有 a+c=m,b+c=n。
1.1 如果 a=b,则两个指针会同时到达两个链表相交的节点,此时返回相交的节点;
1.2 如果 a!=b,则指针分别遍历完本身链表后,两个指针不会同时到达链表的尾节点,然后指针 移到另一个结点头部继续移动,在指针 pA 移动了 a+c+b 次、指针 pB 移动了 b+c+a 次之后,两个指针会同时到达两个链表相交的节点,该节点也是两个指针第一次同时指向的节点,此时返回相交的节点。
2:两链表不相交
2.1 m=n,则两个指针会同时到达两个链表的尾节点,然后同时变成空值 null返回 null;
2.2 m!=n,两个指针不会同时到达两个链表的尾节点,到另一个头部后继续遍历,在都移动了 n+m 次后,两个指针会同时变成空值 null返回 null。
捋清楚之后,可以梳理出代码思路就是
两个指针,各自遍历,遍历完自己遍历对方去,遇到相同结点返回结点,遇不到最后会返回null
代码实现起来很简单
var getIntersectionNode = function (headA, headB) {
if (headA === null || headB === null) return null;
let pA = headA, pB = headB;
while (pA !== pB) {
//这里非常妙,通过我们的推断,其实最多遍历m+n次
pA = pA === null ? headB : pA.next;
pB = pB === null ? headA : pB.next;
}
//跳出循环时,pA===pB,说明要么遍历到了相交点,要么都变成了null
return pA;
};