剑指offer--两个链表的第一个公共结点

题目描述

输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

代码

ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {
		//方法一:对pHead1中的每个结点都去遍历一遍pHead2,比较两者的结点,若有相同的则证明相交,时间复杂度为O(len1*len2)
#if 0
		ListNode* s1 = pHead1;
		ListNode* s2 = pHead2;
		bool same = false;
		while (s1 != NULL)
		{
			s2 = pHead2;
			while (s2 != NULL)
			{
				if (s1 == s2)
				{
					same = true;
					break;
				}
				s2 = s2->next;
		    }
			if (same)
			{
				return s1;
	
			}
			s1 = s1->next;
		}

		return NULL;
#endif
		//方法二:利用哈希缓存:先将pHead1中的每个结点都存入哈希表中,然后对pHead2中的每个结点去哈希表中找。时间复杂度为:O(max(len1+len2);但同时还得增加O(len1)的存储空间存储哈希表
#if 0
		unordered_set<ListNode*> myset;
		ListNode* s1 = pHead1;
		ListNode* s2 = pHead2;
		while (s1 != NULL)
		{
			myset.insert(s1);
			s1 = s1->next;
		}
		while (s2 != NULL)
		{
			bool flag = false;
			if (myset.find(s2) == myset.end())//没有找到相同的结点
			{
				flag = false;
			}
			else
			{
				flag = true;
				return s2;//找到了相同的结点
			}
				
			s2 = s2->next;
		}
		return NULL;



#endif
		//方法三:遍历两次链表,时间复杂度为O(len1+len2)。
#if 0
/*
首先,公共结点是指两个链表从某个结点开始,next指向同一个结点。但由于单向链的每个结点只有一个next,因此从第一个公共结点开始,
两个链表之后的结点都是重合的。
对于两个没有环的链表相交于一节点,则在这个节点之后的所有结点都是两个链表所共有的。
如果它们相交,则最后一个结点一定是共有的,则只需要判断最后一个结点是否相同即可。

如何找到相交的第一个结点,
求出两个链表的长度,然后用长的减去短的得到一个差值 K,然后让长的链表先遍历K个结点,
然后两个链表再同时出发,相遇的第一个结点就是第一个公共结点。
*/
//保存两个链表的最后一个结点进行比较
		ListNode* s1 = pHead1;
		ListNode* s2 = pHead2;
		bool flag = false;
		int lengthofs1 = 0;//链表1的长度
		int lengthofs2 = 0;//链表2的长度
		while (s1 != NULL)
		{
			lengthofs1++;
			if (s1->next == NULL)
			{
				while (s2!=NULL)
				{
					lengthofs2++;
					if (s2->next == NULL)//遍历到了s2的最后一个结点
					{
						if (s1 == s2)
						{
							flag = true;
							break;
						}
					}
					s2 = s2->next;
				}
			}
			if(flag)
				break;
			s1 = s1->next;	
		}


		if (flag)//求出第一个公共结点
		{
			int k = 0;
			s1 = pHead1;
			s2 = pHead2;//重新指向头结点
			if (lengthofs1 > lengthofs2)//链表1长
			{
				k = lengthofs1 - lengthofs2;
				int cont = 0;//记录第二次遍历的长度
				while (s1 != NULL && cont < k)
				{
					cont++;
					s1 = s1->next;
				}
				while (s1 != NULL && s2 != NULL)
				{
					if (s1 == s2)
						return s1;
					s1 = s1->next;
					s2 = s2->next;

				}
			}			
			else
			{
				k = lengthofs2 - lengthofs1;//链表2长
				int cont = 0;//记录第二次遍历的长度
				while (s2 != NULL && cont < k)
				{
					cont++;
					s2 = s2->next;
				}
				while (s1 != NULL && s2 != NULL)
				{
					if (s1 == s2)
						return s1;
					s1 = s1->next;
					s2 = s2->next;

				}
			
			}

		}
		else
		{
			return NULL;//不存在公共结点
		}
		

#endif
     //方法四:使用两个指针,时间复杂度为O(max(len1+len2)
#if 1
/*
如果链表1和链表2的长度相等,则可以定义两个指针分别指向链表1和链表2,然后同时遍历,
在链尾之前有相同的结点则说明相交,并且第一个相同的结点就是公共结点。
现在是链表1和链表2的长度不相等,分别为len1、len2,len1!=len2,但len1+len2=len2+len1
即把链表2的长度加到链表1上(即链表1的开头是链表2的点),链表1的长度加到链表2上
*/
		ListNode* s1 = pHead2;//链表1
		ListNode* s2 = pHead1;//链表2
		while (s1 != s2)
		{
			//if (s1 != NULL)//到最后一个结点
			//{
			//	s1 = s1->next;
			//}//把链表2的长度加到了链表1上
			//else
			//{
			//	s1 = pHead1;
			//}
			s1= s1? s1->next:pHead1 ;
			s2 = s2? s2->next:pHead2;
		}

		return s1;
#endif
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值