「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
链表相交
题目地址点击
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
头脑风暴
其实我一拿到这个题,第一点想的是,想把两个链表反转,然后再遍历两个链表,
找到从哪里开始分叉的,即为相交的点。实际上这个思路是可行的,但是在这一题里,
题目限制了链表必须保持其原始结构,所以放弃。
理论分析
要理解这题的解法,其实明白下面这个图的意思就好了,很简单的小学数学题。
假设两人分别从A、B点出发,以同样的速度跑步,谁点跑到D后,就再从对方的出发点出发,继续跑
问:谁先跑到C点?
解答:
A跑步的路径是(A -> C -> D) + (B -> C) ,长度为h + n + m
B跑步的路径是(B -> C -> D) + (A -> C) ,长度为m + n + h
显而易见,两个人跑步的路程是一样的,都是h + n + m。
并且由于两人速度一样,所以一定同时到达C点!!
题解
那么同理,换到我们这道题,用双指针就可以解决
分别在a1点和b1点创建两个指针n1和n2,两个指针一次都一步,
同时往前走,谁点走到c3,谁就从对方出发点继续走,直到两者相等再停下来。
由于有我们上面数学题的理论分析,这种情况,两者一定会相遇。
代码(javascript)
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
let PA = headA;
let PB = headB;
while(PA != PB){
//A每次向前都一步,如果A走到头了,那么从B点继续向前走
PA = PA === null ? headB : PA = PA.next
//B每次向前都一步,如果B走到头了,那么从A点继续向前走
PB = PB === null ? headA : PB = PB.next
}
return PA
};