题目:
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
- intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
- listA - 第一个链表
- listB - 第二个链表
- skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
- skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数 评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。 处。
核心思路:
方案1: 利用Map数据结构,分别遍历两个链表来实现。
这里面利用了map的键值可以是一个对象的特点,非常方便。
方案2: AB&BA双指针遍历法
这里面一个关键点,就是,我们考虑的时候一定是基于链表的维度考虑的。 跟同事用两个list考虑一会,甚至觉得可以无限循环。。。哈哈哈,
接下来说一下具体的思路吧:
1)循环就一定需要跳出循环的条件,如果A=B跳出循环;
2)循环要有循环条件,也就是遍历终止的条件, while(A !== B);
3)将两个链表长度拉齐,其实关键点就是比较两个指针后段,两个指针同步幅遍历。明确几个点:
3.1)如果两个链表长度相同,同步幅双指针可以直接找到交叉点;
3.2)如果两个链表长度不同,就把两个链表连接成AB、BA两个等长链表,再进行比较。
这种方法就很取巧,对吧。怎么出来的这种思路呢?尝试着做以下推导:
AB链表有交点 -> AB链表最后段一定相同 ->怎么样让后段对齐呢? -> A连接B, B连接A
解:
# 方案1
var getIntersectionNode = function (headA, headB) {
if (!headA || !headB) {
return null
};
let mapA = new Map();
while (headA) {
mapA.set(headA, headA.val);
headA = headA.next;
}
while (headB) {
if (mapA.has(headB)) {
return headB
}
headB = headB.next;
}
return null
};
# 方案2
var getIntersectionNode = function (headA, headB) {
if (!headA || !headB) return null
let A = headA, B = headB;
while (A !== B) {
A = A ? A.next : headB;
B = B ? B.next : headA;
}
return A
};
———— 前端、Javascript实现、算法、刷题、leetcode