携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情
每日刷题 2022.08.02
- leetcode原题链接:leetcode.cn/problems/li…
- 难度:简单
- 方法:数学
题目
- 输入两个链表,找出它们的第一个公共节点。
- 如下面的两个链表
- 在节点 c1 开始相交。
示例
- 示例1
输入: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 个节点。
- 示例2
输入: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 个节点。
- 示例3
输入: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) 内存。
- 本题与主站 160 题相同:leetcode-cn.com/problems/in…
解题思路
- 根据本题的含义:求解两个链表的相交的节点,从示例中可以看出,节点具有相同的值,不代表其是两个链表的相交节点。
- 相交节点,需要值
val
和next
指向的后续节点需要全部相同,才能够认为这两个节点是两个链表的相交节点。 - 记第一个链表为
a
,第二个链表为b
- 最直观也是最好想的解法,使用
map
哈希表来存储链表a
中的每一个节点,再遍历链表b
的时候,依次判断是否存在和map
中相同的节点;如果存在的话,就返回即可;直到找完b
链表都没有找到相同的节点,那么就说明两个链表不存在相交的节点,返回null
- 最直观也是最好想的解法,使用
另一种思路
- 大家都说这是:浪漫的相遇题目
- 我变成你走过你来时的路,你变成我走过我来时的路,之后我们就相遇了。
- 非常巧妙,总的路径是一样的,相遇的时候,就是两个链表的相交节点。
最后的疑问
- 最后你可能还会存在疑问🤔️,那如果两个链表不存在相交的节点怎么办呢?
- 由图可知,两个链表不存在相交的节点的时候,会在最终同时等于
null
,跳出循环。
AC
代码
- 浪漫相遇的解法
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
// 你变成我,走过我来时的路
// 我变成你,走过你来时的路
// 之后我们就相遇了
let a = headA, b = headB;
while(a != b) {
// 同时结束,到末尾,两个都是null,因此跳出循环
a = a == null ? headB : a.next;
b = b == null ? headA : b.next;
}
return a;
};
附录
- 人生尚未结束,何处是故乡?