问题描述:
给你两个单链表的头节点 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 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
解题思路:
方法1:集合
- 定义一个集合visited
- 遍历链表A, 将其中的元素全部push到集合中
- 接着,遍历链表B,判断其中的每一个元素是否出现在集合中,如果出现,直接返回该元素。
代码实现(js)
/**
* 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 visited = new Set()
let temp = headA
while(temp !== null){
visited.add(temp)
temp = temp.next
}
temp = headB
while(temp !== null){
if(visited.has(temp)){
return temp
}
temp = temp.next
}
return null
};
方法二:双指针
- 设链表A, B的公共节点为node, 链表A长度为a, 链表B长度为b, 链表A, B公共部分长度为c
- 对于链表A, 头节点到node节点之间的长度为a - c
- 对于链表B, 头节点到node节点之间的长度为b - c
- 构建两个指针pA, pB, 分别指向链表A, B的头节点
- 指针pA先遍历链表A, 再遍历链表B, 走到node节点,长度为: a + (b - c)
- 指针pB先遍历链表B, 再遍历链表A, 走到node节点,长度为:b + (a - c)
- 此时两指针重合,表明:a + (b - c) = b + (a - c)
- 如果两个链表有公共部分,两指针同时指向公共节点node
- 如果两个链表没有公共部分,返回null
/**
* 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) {
// 1.首先判断headA,headB是否为空
if(headA === null || headB === null){
return null
}
// 2.定义两个指针pA, pB
let pA = headA
let pB = headB
// 3.如果pA,pB不相等
while(pA !== pB){
pA = pA === null ? headB : pA.next
pB = pB === null ? headA : pB.next
}
return pA
};