描述
输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
方法一
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function FindFirstCommonNode(pHead1, pHead2)
{
if(pHead1==null||pHead2== null) return null
let p1 = pHead1
let p2 = pHead2
while(p1!==p2)
{
p1 = p1.next
p2 = p2.next
//刚好长度一样,循环到相同的公共节点,可以停止了
if(p1 ===p2) break;
//这一步是关键!真的太聪明了,第一次比完之后,因为对位相等,长度不同肯定没有匹配的,但在第二次循环完毕之后,不管长度相差几都会找到第一个公共节点
if(p1 == null) return p1 = pHead2
if(p2 == null) return p2 = pHead1
}
return p1
}
module.exports = {
FindFirstCommonNode : FindFirstCommonNode
};
这个异常简洁,完全是用了一个巧妙的方法,就跟俄罗斯方块一样,当事个链表,循环到第二轮次时,两个链表交换拼接,长度就会一样,此时的最后n个同的链表节点,就会一致
方法二
较为常规,代码较长,但是容易理解
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function FindFirstCommonNode(pHead1, pHead2) {
if (pHead1 == null || pHead2 == null) return null;
let p1 = pHead1;
let p2 = pHead2;
let len1 = 0;
let len2 = 0;
//先计算出每个链表的长度
while(p1!==null){
len1++;
p1 = p1.next;
}
while(p2!==null){
len2++;
p2 = p2.next
}
//将较长的链表的头节点,指到跟较短链表相同长度头节点的位置
if(len1>=len2){
for(let i = 0; i<len1-len2;i++){
pHead1 = pHead1.next
}
}else{
for(let i = 0; i<len2-len1; i++){
pHead2 = pHead2.next
}
}
//指到相同位置之后,开始挨个比较,此时有相同的肯定会比较出来,因为长度已经一样了,如果没有相同的则一定返回是空
//此处限制它不为空,主要担心在上面的找亲的头节点点位置时,已经循环完毕
while(pHead1!==null&&pHead2!==null){
if(pHead1==pHead2){
return pHead1
}
pHead1 = pHead1.next
pHead2 = pHead2.next
}
return null
}
module.exports = {
FindFirstCommonNode: FindFirstCommonNode,
};