输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
数据范围:
要求:空间复杂度
,时间复杂度 )
要求:空间复杂度
例如,输入{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 {
* 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* tmpHead1 = pHead1;
struct ListNode* tmpHead2 = pHead2;
int longth1 = 0;
int longth2 = 0;
if (!pHead1 || !pHead2) {
return NULL;
}
while (tmpHead1->next) {
tmpHead1 = tmpHead1->next;
longth1++;
}
while (tmpHead2->next) {
tmpHead2 = tmpHead2->next;
longth2++;
}
if (tmpHead2 != tmpHead1)
{
return NULL;
}
tmpHead1 = pHead1;
tmpHead2 = pHead2;
while (tmpHead1 != tmpHead2) {
tmpHead1 = tmpHead1->next ?: pHead2;
tmpHead2 = tmpHead2->next ?: pHead1;
}
return tmpHead1;
} 先判断两个链表是否有公共节点。 再去找公共节点。(大前提要确定两个链表没环)
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; //未找到
} 核心思想:两个链表的长度差
/* 找出2个链表的长度,然后让长的先走两个链表的长度差,然后再一起走 (因为2个链表用公共的尾部) */ class Solution { public: ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) { int len1 = findListLenth(pHead1); int len2 = findListLenth(pHead2); if(len1 > len2){ pHead1 = walkStep(pHead1,len1 - len2); }else{ pHead2 = walkStep(pHead2,len2 - len1); } while(pHead1 != NULL){ if(pHead1 == pHead2) return pHead1; pHead1 = pHead1->next; pHead2 = pHead2->next; } return NULL; } int findListLenth(ListNode *pHead1){ if(pHead1 == NULL) return 0; int sum = 1; while(pHead1 = pHead1->next) sum++; return sum; } ListNode* walkStep(ListNode *pHead1, int step){ while(step--){ pHead1 = pHead1->next; } return pHead1; } };