10.两个链表的第一个公共节点

这是一道关于链表操作的问题,目标是输入两个链表并找出它们的第一个公共节点。暴力解法的时间复杂度较高,为m*n,而更优的解法只需遍历一次两个链表,时间复杂度为O(m+n)。当链表存在公共节点时,两个指针会一起遍历到公共节点然后到达末尾。例如,两个链表a->b->1->d->nullptr和2->1->d->nullptr,它们的第一个公共节点是1。
摘要由CSDN通过智能技术生成
  • 题目:
    输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

  • 暴力解法,时间复杂度为(m*n)

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
    if(pHead1==nullptr || pHead2==nullptr)
        return nullptr;
    ListNode* p1=pHead1,*p2=pHead2;
    while(p1!=nullptr && p2!=nullptr)
    {
        while(p2!=nullptr)
        {
            if(p1==p2)
                return p1;
            else
                p2=p2->next;
        }
        p1=p1->next;
        p2=pHead2;
    }
     return nullptr;
    }
};
  • 好方法:时间复杂度为O(m+n);没有相同节点时,p1和p2分别将来两个链表都遍历一次;

如该两个链表有相同的节点,那么它们会一起从相同节点走到末尾;
a->b->1->d->nullptr;
2->1->d->nullptr;

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(pHead1==nullptr || pHead2==nullptr)
            return nullptr;
        ListNode* p1=pHead1,*p2=pHead2;
        while(p1!=p2) //循环终止条件,有相同节点时,p1指向相同节点,没有时p1和p2都指向空;
        {
            p1=p1->next;
            p2=p2->next;
            if(p1 != p2)
            {
                if(p1==nullptr) p1=pHead2;
                if(p2==nullptr) p2=pHead1;
            }
        }
        return p1;
    }
};
  • 测试代码:
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<sstream>
#include<cmath>
#include<unordered_map>

using namespace std;

struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(pHead1==nullptr || pHead2==nullptr)
            return nullptr;
        ListNode* p1=pHead1,*p2=pHead2;
        int count=0;
        while(p1!=p2)
        {
            count++;
            p1=p1->next;
            p2=p2->next;
            if(p1 != p2)
            {
                if(p1==nullptr) 
                    p1=pHead2;
                if(p2==nullptr)  //1 2 3 4 5  6  7 8 9  p1
                    p2=pHead1;   //1 3 6 7 8  9         p2
            }
        }
        cout<<"while run "<<count<<endl; 
        return p1;
    }
    int CountNode(ListNode* head)
    {
        int i=0;
        if(head==nullptr)
          return i;
        ListNode *p=head;
        while(p!=nullptr)
         {
             i++;
             p=p->next;
         }
         return i;
    }
};

int main()
{
    ListNode *pHead1=new ListNode(1);
    ListNode *pHead2=new ListNode(2);
    ListNode *pHead3=new ListNode(3);
    ListNode *p1=pHead1,*p2=pHead2,*p3=pHead3;
    for(int i=3;i<12;i++)
        {
            ListNode *p=new ListNode(i);
            p1->next=p;
            if(i>=5)
            {
                p3->next=p;
                p3=p3->next;
            }
            p1=p1->next;
        } 
    for(int i=5;i<8;i++)
        {
            ListNode *p=new ListNode(i);
            p2->next=p;
            p2=p2->next;
        } 
   
    Solution sol;
    int c1=sol.CountNode(pHead1);
    int c2=sol.CountNode(pHead2);
    int c3=sol.CountNode(pHead3);
    cout<<"c1 node count is "<<c1<<endl;
    cout<<"c2 node count is "<<c2<<endl;
    cout<<"c3 node count is "<<c3<<endl;
    ListNode *result2=sol.FindFirstCommonNode(pHead1,pHead2);
    ListNode *result3=sol.FindFirstCommonNode(pHead1,pHead3);
    //cout<<result->val<<endl;
    if(result2==nullptr)
       cout<<"result2:is nullptr"<<endl;
    else
    {
        cout<<"result2 same node val is "<<result2->val<<endl;
    }
    if(result3==nullptr)
       cout<<"result3: is nullptr"<<endl;
    else
    {
        cout<<"result3 same node val is "<<result3->val<<endl;
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值