给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
链表的长度不一定相等,也就是说两个链表的交点不一定是在他们所在链表的同一位置。
问题分析:
如果同时分别遍历 A 和 B 链表,去比较是否相交的前提是他们的长度相同。假设反复不停的分别遍历 A 和 B,那么经过 N 次之后定会相交.图解:
但是在图中可以看出一个问题,就是遍历的次数过多, B 表 比 A 表元素少一个,那么 A遍历完一次之后,B遍历到了倒数第二个,那么 A开始重新遍历,B开始遍历到最后一个,当 A遍历到第二个的时候, B开始重新遍历,那么最终他们遍历的下标仅仅差了1个,即
当两个链表都进入第二次遍历时, A 遍历下标为 1, B 遍历下标为 0, 原本一开始遍历的时候都是从0开始的
那么很可能就要遍历多次才能找到相交点,照此方法实现:
**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
let pA = headA
let pB = headB
if (pA === null || pB === null) {
return null
}
while(pA !== pB) {
pA = pA === null ? headA : pA.next
pB = pB === null ? headB : pB.next
}
return pB
};
执行结果:
很显然内存消耗实在太大,执行用时也超出了预期。那么其实可以是在遍历方法上进行优化,达到减少遍历的次数。
当A表遍历完了之后,就遍历B表。 B表遍历完了之后立即遍历A表,以此遍历,最多2次遍历即可找到相交点。
图解:
优化后:
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
let pA = headA
let pB = headB
if (pA === null || pB === null) {
return null
}
while(pA !== pB) {
// 将此处作修改
pA = pA === null ? headB : pA.next
pB = pB === null ? headA : pB.next
}
return pB
};
结果:
很明显优化后的执行效率更高!