题目:
在本题中,单链表可能有环也可能无环,给定两个单链表的头结点phead1 和phead2,这两个链表可能相交也可能不相交,请实现一个函数,如果两个链表相交,请返回相交的第一个节点,如果不相交,直接返回null
要求:如果链表1的长度为n,链表2的长度为m,时间复杂度请达到O(N + M),额外空间复杂度达到O(1)
这个问题可以拆分成三个子问题:
一:如何判断一个链表是否有环,如果有,则返回第一个进入环的子节点,没有返回null
二:如花判断两个无环链表是否相交,相交则返回第一个相交的节点,不相交则返回null
三:如何判断两个有环链表是否相交,相交则返回第一个相交的节点,不相交则返回null
注意:如果一个链表有环,另一个链表无环,它们是不可能相交的,直接返回null
代码:
//判断是否有环
function getLoopNode(head) {
if (head == null || head.next == null || head.next.next == null) {
return null;
}
var n1 = head.next;
var n2 = head.next.next;
while (n1 != n2) {
if (n2.next == null || n2.next.next == null) {
return null
}
n1 = n1.next;
n2 = n2.next.next;
}
n2 = head;
while (n1 !== n2) {
n1 = n1.next;
n2 = n2.next;
}
return n1;
}
//两个无环链表
function noLoop(pHead1, pHead2) {
if(pHead1 == null || pHead2 == null){
return null;
}
var cur1 = pHead1;
var cur2 = pHead2;
var n = 0;
while(cur1.next !== null){
n++;
cur1 = cur1.next;
}
while(cur2 !== null){
n--;
cur2 = cur2.next;
}
if(cur1 !== cur2){
return null;
}
cur1 = n > 0 ? pHead1 : pHead2;
cur2 = cur1 === pHead1 ? pHead2 : pHead1;
n = Math.abs(n);
while(n != 0){
n--;
cur1 = cur1.next;
}
while(cur1 != cur2){
cur1 = cur1.next;
cur2 = cur2.next;
}
return cur1;
}
//两个有环
function bothLoop(pHead1, loop1, pHead2, loop2) {
var cur1 = null;
var cur2 = null;
if (loop1 == loop2) {
if (pHead1 == null || pHead2 == null) {
return null;
}
var cur1 = pHead1;
var cur2 = pHead2;
var n = 0;
while (cur1.next !== null) {
n++;
cur1 = cur1.next;
}
while (cur2 !== null) {
n--;
cur2 = cur2.next;
}
if (cur1 !== cur2) {
return null;
}
cur1 = n > 0 ? pHead1 : pHead2;
cur2 = cur1 === pHead1 ? pHead2 : pHead1;
n = Math.abs(n);
while (n != 0) {
n--;
cur1 = cur1.next;
}
while (cur1 != cur2) {
cur1 = cur1.next;
cur2 = cur2.next;
}
return cur1;
}else{
cur1 = loop1.next;
while(cur1 != loop1){
if(cur1 == cur2){
return loop1;
}
cur1 = cur1.next;
}
return null
}
}
//总函数
function getIntersectNode(pHead1,pHead2){
if(pHead1 == null || pHead2 == null){
return null;
}
var loop1 = getLoopNode(pHead1);
var loop2 = getLoopNode(pHead2);
if(loop1 == null && loop2 == null){
return noLoop(pHead1,pHead2)
}
if(loop1 !== null && loop2 !== null){
return bothLoop(pHead1,loop1,pHead2,loop2)
}
return null;
}