输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
数据范围:
要求:空间复杂度 ,时间复杂度
要求:空间复杂度 ,时间复杂度
例如,输入{1,2,3},{4,5},{6,7}时,两个无环的单向链表的结构如下图所示:
可以看到它们的第一个公共结点的结点值为6,所以返回结点值为6的结点。
输入分为是3段,第一段是第一个链表的非公共部分,第二段是第二个链表的非公共部分,第三段是第一个链表和第二个链表的公共部分。 后台会将这3个参数组装为两个链表,并将这两个链表对应的头节点传入到函数FindFirstCommonNode里面,用户得到的输入只有pHead1和pHead2。
返回传入的pHead1和pHead2的第一个公共结点,后台会打印以该节点为头节点的链表。
{1,2,3},{4,5},{6,7}
{6,7}
第一个参数{1,2,3}代表是第一个链表非公共部分,第二个参数{4,5}代表是第二个链表非公共部分,最后的{6,7}表示的是2个链表的公共部分 这3个参数最后在后台会组装成为2个两个无环的单链表,且是有公共节点的
{1},{2,3},{}
{}
2个链表没有公共节点 ,返回null,后台打印{}
struct ListNode* henFindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2 ) { if (!pHead1) { return NULL; } if (!pHead2) { return NULL; } struct ListNode*p1=pHead1; struct ListNode*p2=pHead2; int n1=0; int n2=0; while (p1!=NULL) { p1=p1->next; n1++; } p1=pHead1; while (p2!=NULL) { p2=p2->next; n2++; } p2=pHead2; if (n1>n2) { for (int i=0;i<n1-n2; i++) { p1=p1->next; } } if (n1<n2) { for (int i=0;i<n2-n1; i++) { p2=p2->next; } } while (p1!=p2) { p1=p1->next; p2=p2->next; } return p1; }使输入的两个链表的尾部对齐
struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2 ) { struct ListNode *p1, *p2 = pHead2; if(pHead1==NULL || pHead2==NULL) return NULL; while(p2!=NULL) { p1 = pHead1; while(p1!=NULL) { if(p1==p2) return p1; p1 = p1->next; } p2 = p2->next; } return NULL; }
struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2 ) { // write code here //1\第一个的尾连接到第二个的头,是环状则返回值,不是环状就返回空 //2\两个指针分别走两个链表 struct ListNode* n1 = pHead1; struct ListNode* n2 = pHead2; int cnt = 0; for(n1=pHead1;n1!=NULL&&cnt<1000;n1=n1->next) { for(n2=pHead2;n2!=NULL&&cnt<1000;n2=n2->next) { if(n1 == n2) { return n1; } } } return NULL; }
/** * struct ListNode { * int val; * struct ListNode *next; * }; */ /** * @param pHead1 ListNode类 * @param pHead2 ListNode类 * @return ListNode类 */ struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) { // write code here struct ListNode* slow = pHead; struct ListNode* fast = pHead; while (fast && fast->next) { slow = slow->next; fast = fast->next->next; if (slow == fast) break; } if (!fast || !fast->next) return NULL; else { slow = pHead; while (slow != fast) { slow = slow->next; fast = fast->next; } return slow; }; } struct ListNode* FindFirstCommonNode(struct ListNode* pHead1,struct ListNode* pHead2 ) { struct ListNode* p1 = pHead1; struct ListNode* p2 = pHead2; struct ListNode* tail = p1; if (!p1 || !p2) return NULL; else if (p1 == p2) return p1; else { while (tail->next) tail=tail->next; tail->next = p2; p2 = EntryNodeOfLoop(p1); if(!p2){ tail->next = NULL; return NULL; }else { tail->next = NULL; return p2; } } }
/** * struct ListNode { * int val; * struct ListNode *next; * }; */ /** * * @param pHead1 ListNode类 * @param pHead2 ListNode类 * @return ListNode类 */ struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2 ) { // write code here if (pHead1 == NULL || pHead2 == NULL) { return NULL; } struct ListNode* ptr1 = pHead1, *ptr2 = pHead2; while (ptr1) { ptr2 = pHead2; while (ptr2) { if (ptr1 == ptr2) { return ptr1; }else { ptr2 = ptr2->next; } } ptr1 = ptr1->next; } return NULL; }
2个指针同时把2个链表都跑一遍,这个想法太秒了
struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2 ) { // write code here struct ListNode* p = pHead1; struct ListNode* q = pHead2; while(p!=NULL || q!=NULL) { if(p!=NULL&&q!=NULL&&p->val==q->val) break; if(p==NULL) p=pHead2; else p=p->next; if(q==NULL) q=pHead1; else q=q->next; } return p; }
struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2 ) { struct ListNode *p1 = pHead1; struct ListNode *p2 = pHead2; while(p1!=p2){ p1 = (p1==NULL ? pHead2 : p1->next); p2 = (p2==NULL ? pHead1 : p2->next); } return p1; // write code here }
/** * struct ListNode { * int val; * struct ListNode *next; * }; */ /** * * @param pHead1 ListNode类 * @param pHead2 ListNode类 * @return ListNode类 */ struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2 ) { // write code here struct ListNode* p1 = pHead1, *p2 = pHead2; if (pHead1 == NULL || pHead2 == NULL) return NULL; while (p1 != p2) { p1 = p1->next; p2 = p2->next; if (p1 != p2) {//这一步非常重要 都到表尾NULL也相等 if (p1 == NULL) { p1 = pHead2; } if (p2 == NULL) { p2 = pHead1; } } } return p1; }
struct ListNode* FindFirstCommonNode(struct ListNode* pHead1, struct ListNode* pHead2 ) { //若一个链表为空,则没有公共结点 if (pHead1 == NULL || pHead2 == NULL) { return NULL; } int count1 = 0, count2 = 0; struct ListNode* cur1 = pHead1, *cur2 = pHead2; //计算链表1的结点个数 while (cur1) { count1++; cur1 = cur1->next; } //计算链表2的结点个数 while (cur2) { count2++; cur2 = cur2->next; } cur1 = pHead1; cur2 = pHead2; int dif = count1 - count2; //计算差值 if (dif > 0) //链表1长,所以链表1的指针要先走dif步 { while (dif--) { cur1 = cur1->next; } } else if (dif < 0) //链表2长,所以链表2的指针要先走ABS(dif)步 { while (dif++) { cur2 = cur2->next; } } //此时2个链表长度相等,指针一起走 while (cur1) { if (cur1 == cur2 && cur1 != NULL) { return cur1; //找到了第一个公共结点 } cur1 = cur1->next; cur2 = cur2->next; } return NULL; //未找到 }核心思想:两个链表的长度差