- 常规输入检查
- 检查 2 个链表是否有共同的 tail, 若无 则不存在公共节点,直接返回 NULL;若tail 相同,则说明有公共节点,继续以下步骤
- 上述找 tail 过程,顺便记录 2 条 链表的长度,分别记为 x + z 和 y + z。 其中 x 代表 链表 1 除去 公共部分的 长度,y 代表 链表 2 除去 公共部分的 长度, z 代表 公共部分长度。
- 将 较短的一条链表(假设是链表 1)反转,则此时 链表 2 的长度为 x + y。(反转后 链表1的 新 head 即原先的 tail)
- 计算出 x, y, z
- 从 反转后的链表的 新 head 处(原 tail), 进行确定长度 z 的链表反转
- 再次反转后的 新 head 即为 两个链表的公共节点。
// declares
struct ListNode* ReverseList(struct ListNode* pHead );
int ListLen(struct ListNode* pHead );
struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2 ) {
// 常规输入检查
if (!pHead1 || !pHead2 || (!pHead1->next && !pHead2->next)){
return NULL;
}
// 检查 2 个链表是否有共同的 tail
struct ListNode* pTail1 = pHead1;
struct ListNode* pTail2 = pHead2;
int count1 = 1;
int count2 = 1;
while(pTail1->next){
count1++;
pTail1 = pTail1->next;
if(count1 > 1000){ return NULL; }
}
while(pTail2->next){
count2++;
pTail2 = pTail2->next;
if(count2 > 1000){ return NULL; }
}
// 若不等 则不存在公共节点,直接返回 NULL
if (pTail1 != pTail2){
return NULL;
}
int x_z = count1;
int y_z = count2;
// 如果 链表1 长,则将两者调换一下
if (x_z > y_z){
x_z ^= y_z;
y_z ^= x_z;
x_z ^= y_z;
struct ListNode* temp = pHead1;
pHead1 = pHead2;
pHead2 = temp;
}
// 翻转 短链表
struct ListNode* tail = ReverseList(pHead1);
int x_y = ListLen(pHead2);
// 计算 x,y,z
int x = (x_z + x_y - y_z) >> 1;
int y = x_y - x;
int z = x_z - x;
// 再次翻转给定长度 z
struct ListNode* pFore = tail;
struct ListNode* p = tail->next;
tail->next = NULL;
for(int i = 1; i < z; i++){
struct ListNode* pn = p->next;
p->next = pFore;
pFore = p;
p = pn;
}
// 大功告成
return pFore;
}
// 计数
int ListLen(struct ListNode* pHead ){
int count = 0;
while(pHead){
count++;
pHead = pHead->next;
if(count > 2000){ return 0; }
}
return count;
}
// 翻转
struct ListNode* ReverseList(struct ListNode* pHead ) {
if (!pHead || !pHead->next){
return pHead;
}
struct ListNode* pFore = pHead;
struct ListNode* p = pHead->next;
pHead->next = NULL;
while(p){
struct ListNode* pn = p->next;
p ->next = pFore;
pFore = p;
p = pn;
}
return pFore;
}