解法1: 最简单的方法。两链表同时开始遍历,算长度。然后长的那个截去多余长度再重新开始遍历,如果遍历过程中有两节点一样则返回该节点,否则返回NULL。
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (!headA || !headB) return NULL;
int countA=0;
int countB=0;
ListNode* nodeA=headA;
ListNode* nodeB=headB;
while(nodeA) {
countA++;
nodeA=nodeA->next;
}
while(nodeB) {
countB++;
nodeB=nodeB->next;
}
ListNode* shortListHead = (countA<countB)? headA : headB;
ListNode* longListHead = (countA>=countB)? headA : headB;
for (int i=0; i<abs(countA-countB); ++i)
longListHead=longListHead->next;
while(shortListHead) { //now shortList and longList have the same length
if (shortListHead==longListHead) return shortListHead;
else {
shortListHead=shortListHead->next;
longListHead=longListHead->next;
}
}
return NULL;
}
解法2: 其中一链表变环,然后就跟求链表环首地址一样了。要用快慢指针。下次补充。
解法3:两链表同时遍历,短的那个变环。假设短链表长度为a, 长链表长度为b, 如果他们尾部有交集,则短的那个到最后时,长的那个还有b-a才到最后。这时,我们把短链表首尾相连,然后p1指向长链表遍历所在的当前位置(的下一个位置), p2指向长链表的头部,同时开始遍历,则p1再走b-a+a=b步就到了相交处,p2走b步也到了相交处,此时p1和p2重合。如果p2走完了也没有发现和p1重合,则返回NULL。
代码如下:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (!headA || !headB) return NULL;
ListNode* p1=headA;
ListNode* p2=headB;
ListNode* pEndA;
ListNode* pEndB;
while(p1 && p2) {
if (p1==p2) return p1;
if (p1->next && p2->next) { //Note the [1] and [1] case
p1=p1->next;
p2=p2->next;
}else break;
}
if (p1->next==NULL) {
if (!p2 || !p2->next) return NULL;
pEndA=p1;
p1->next=headA;
p1=p2->next;
p2=headB;
while(p1 && p2 && p1!=p2) {
p1=p1->next;
p2=p2->next;
}
pEndA->next=NULL; //remove the cycle to resume the link list
if (p1==p2) return p1;
else return NULL;
} else if (p2->next==NULL) {
if (!p1 || !p1->next) return NULL;
pEndB=p2;
p2->next=headB;
p2=p1->next;
p1=headA;
while(p1 && p2 && p1!=p2) {
p1=p1->next;
p2=p2->next;
}
pEndB->next=NULL; //remove the cycle to resume the link list
if (p1==p2) return p2;
else return NULL;
}
return NULL;
}
注意:
1)变环了最后要断开,不能破坏链表结构。
2)注意各种相交,重合,和不重合的case。
此题测试例子较多。代码如下:
int main()
{
cout<<"test case 1"<<endl;
ListNode a0_1(3);
ListNode a0_2(4);
ListNode b0_1(9);
ListNode b0_2(12);
ListNode b0_3(72);
ListNode c0_1(8);
ListNode c0_2(45);
ListNode c0_3(29);
a0_1.next=&a0_2;
a0_2.next=&c0_1;
c0_1.next=&c0_2;
c0_2.next=&c0_3;
b0_1.next=&b0_2;
b0_2.next=&b0_3;
b0_3.next=&c0_1;
ListNode *t=getIntersectionNode(&a0_1, &b0_1);
if (t) cout<<t->val<<endl;
cout<<"test case 2"<<endl;
ListNode a1_1(1);
ListNode a1_2(3);
ListNode a1_3(5);
ListNode a1_4(7);
ListNode a1_5(9);
ListNode a1_6(11);
ListNode a1_7(13);
ListNode a1_8(15);
ListNode a1_9(17);
ListNode a1_10(19);
ListNode a1_11(21);
ListNode b1_1(2);
a1_1.next=&a1_2;
a1_2.next=&a1_3;
a1_3.next=&a1_4;
a1_4.next=&a1_5;
a1_5.next=&a1_6;
a1_6.next=&a1_7;
a1_7.next=&a1_8;
a1_8.next=&a1_9;
a1_9.next=&a1_10;
a1_10.next=&a1_11;
t=getIntersectionNode(&a1_1, &b1_1);
if (t) cout<<t->val<<endl;
cout<<"test case 3"<<endl;
ListNode a2_1(1);
ListNode a2_2(2);
ListNode a2_3(3);
ListNode a2_4(4);
ListNode a2_5(5);
ListNode a2_6(6);
ListNode a2_7(7);
ListNode a2_8(8);
ListNode a2_9(9);
ListNode a2_10(10);
ListNode a2_11(11);
ListNode a2_12(12);
ListNode a2_13(13);
a2_1.next=&a2_2;
a2_2.next=&a2_3;ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (!headA || !headB) return NULL;
ListNode* p1=headA;
ListNode* p2=headB;
ListNode* pEndA;
ListNode* pEndB;
while(p1 && p2) {
if (p1==p2) return p1;
if (p1->next && p2->next) { //Note the [1] and [1] case
p1=p1->next;
p2=p2->next;
}else break;
}
if (p1->next==NULL) {
if (!p2 || !p2->next) return NULL;
pEndA=p1;
p1->next=headA;
p1=p2->next;
p2=headB;
while(p1 && p2 && p1!=p2) {
p1=p1->next;
p2=p2->next;
}
pEndA->next=NULL; //remove the cycle to resume the link list
if (p1==p2) return p1;
else return NULL;
} else if (p2->next==NULL) {
if (!p1 || !p1->next) return NULL;
pEndB=p2;
p2->next=headB;
p2=p1->next;
p1=headA;
while(p1 && p2 && p1!=p2) {
p1=p1->next;
p2=p2->next;
}
pEndB->next=NULL; //remove the cycle to resume the link list
if (p1==p2) return p2;
else return NULL;
}
return NULL; //???
}
a2_3.next=&a2_4;
a2_4.next=&a2_5;
a2_5.next=&a2_6;
a2_6.next=&a2_7;
a2_7.next=&a2_8;
a2_8.next=&a2_9;
a2_9.next=&a2_10;
a2_10.next=&a2_11;
a2_11.next=&a2_12;
a2_12.next=&a2_13;
ListNode *pb1=&a2_1;
ListNode *pb2=&a2_2;
ListNode *pb3=&a2_3;
ListNode *pb4=&a2_4;
ListNode *pb5=&a2_5;
ListNode *pb6=&a2_6;
ListNode *pb7=&a2_7;
ListNode *pb8=&a2_8;
ListNode *pb9=&a2_9;
ListNode *pb10=&a2_10;
ListNode *pb11=&a2_11;
ListNode *pb12=&a2_12;
ListNode *pb13=&a2_13;
t=getIntersectionNode(&a2_1, pb1);
if (t) cout<<t->val<<endl;
cout<<"test case 4"<<endl;
ListNode a3_1(3);
ListNode a3_2(4);
ListNode a3_3(5);
ListNode a3_4(6);
ListNode a3_5(7);
ListNode a3_6(8);
ListNode a3_7(9);
ListNode a3_8(10);
ListNode a3_9(11);
ListNode a3_10(12);
ListNode a3_11(13);
ListNode a3_12(14);
ListNode a3_13(15);
a3_1.next=&a3_2;
a3_2.next=&a3_3;
a3_3.next=&a3_4;
a3_4.next=&a3_5;
a3_5.next=&a3_6;
a3_6.next=&a3_7;
a3_7.next=&a3_8;
a3_8.next=&a3_9;
a3_9.next=&a3_10;
a3_10.next=&a3_11;
a3_11.next=&a3_12;
a3_12.next=&a3_13;
ListNode b3_1(2);
ListNode *pb3_2=&a3_1;
ListNode *pb3_3=&a3_2;
ListNode *pb3_4=&a3_3;
ListNode *pb3_5=&a3_4;
ListNode *pb3_6=&a3_5;
ListNode *pb3_7=&a3_6;
ListNode *pb3_8=&a3_7;
ListNode *pb3_9=&a3_8;
ListNode *pb3_10=&a3_9;
ListNode *pb3_11=&a3_10;
ListNode *pb3_12=&a3_11;
ListNode *pb3_13=&a3_12;
ListNode *pb3_14=&a3_13;
b3_1.next=pb3_2;
t=getIntersectionNode(&a3_1, &b3_1);
if (t) cout<<t->val<<endl;
cout<<"test case 5"<<endl;
ListNode a5_1(1);
ListNode a5_2(3);
ListNode a5_3(5);
ListNode a5_4(7);
ListNode a5_5(9);
ListNode a5_6(10);
ListNode a5_7(11);
ListNode a5_8(12);
ListNode a5_9(13);
ListNode a5_10(14);
ListNode a5_11(15);
ListNode a5_12(16);
ListNode a5_13(17);
ListNode a5_14(18);
ListNode a5_15(19);
ListNode a5_16(20);
ListNode a5_17(21);
ListNode a5_18(22);
ListNode a5_19(23);
ListNode a5_20(24);
ListNode a5_21(25);
ListNode a5_22(26);
a5_1.next=&a5_2;
a5_2.next=&a5_3;
a5_3.next=&a5_4;
a5_4.next=&a5_5;
a5_5.next=&a5_6;
a5_6.next=&a5_7;
a5_7.next=&a5_8;
a5_8.next=&a5_9;
a5_9.next=&a5_10;
a5_10.next=&a5_11;
a5_11.next=&a5_12;
a5_12.next=&a5_13;
a5_13.next=&a5_14;
a5_14.next=&a5_15;
a5_15.next=&a5_16;
a5_16.next=&a5_17;
a5_17.next=&a5_18;
a5_18.next=&a5_19;
a5_19.next=&a5_20;
a5_20.next=&a5_21;
a5_21.next=&a5_22;
ListNode *pb5_1=&a5_6;
ListNode *pb5_2=&a5_7;
ListNode *pb5_3=&a5_8;
ListNode *pb5_4=&a5_9;
ListNode *pb5_5=&a5_10;
ListNode *pb5_6=&a5_11;
ListNode *pb5_7=&a5_12;
ListNode *pb5_8=&a5_13;
ListNode *pb5_9=&a5_14;
ListNode *pb5_10=&a5_15;
ListNode *pb5_11=&a5_16;
ListNode *pb5_12=&a5_17;
ListNode *pb5_13=&a5_18;
ListNode *pb5_14=&a5_19;
ListNode *pb5_15=&a5_20;
ListNode *pb5_16=&a5_21;
ListNode *pb5_17=&a5_22;
t=getIntersectionNode(&a5_1, pb5_1);
if (t) cout<<t->val<<endl;
return 0;
}