单链表——判断两个单链表(无头节点)是否相交,如果相交,返回单链表的第一个结点

本博客主要记录两个解法:
1.求两个单链表的节点个数,消除结点个数不同带来的影响,两个指针一起走,相遇即相交点。
2.数学方式求解。

一、求结点个数,消除结点个数不同带来的影响,俩指针同步走

思路:两个单链表相从相交的第一个结点开始,后面的结点都共享,所以两个单链表的节点个数之差就是相交的结点之前,两个单链表的结点个数之差,我们只需要将两个单链表结点个数之差算出来,然后消除结点个数不同带来的影响,让p1和p2同时向后走,那么相遇的时候,即相交的第一个结点,如下图:
在这里插入图片描述
p1和p2分别从两个单链表的如下位置同时向后走,那么p1和p2相遇时的结点即为相交的第一个节点(如果不相交,那么p1和p2最终都会指向NULL)
在这里插入图片描述
代码:

//不相交,返回NULL,相交返回第一个相交的结点
ListNode* FindTheSameNode(ListNode* head1, ListNode* head2)
{
	if (head1 == NULL || head2 == NULL)//两个单链表都是空的
	{
		return NULL;
	}
	
	ListNode* p1 = head1;
	int num1 = 0;//记录第一个单链表的节点个数
	ListNode* p2 = head2;
	int num2 = 0;//记录第二个单链表的结点个数

	while (p1 != NULL)//计算第一个单链表的节点个数
	{
		++num1;
		p1 = p1->next;
	}
	while (p2 != NULL)//计算第二个单链表的节点个数
	{
		++num2;
		p2 = p2->next;
	}
	p1 = head1;
	p2 = head2;

	//让p1或者p2把节点个数的差值的影响去除
	while (num1 > num2)
	{
		p1 = p1->next; 
		num1--;
	}
	while (num2 > num1)
	{
		p2 = p2->next;
		num2--;
	}

	while (p1 != p2)//如果相交,则退出时p1 == p2,指向"相交的第一个结点",如果不相交,则最后p1 == p2 == NULL
	{
		p1 = p1->next;
		p2 = p2->next;
	}
	return p1;
}

二、数学思维

思路:
如下图,假设相交的结点之前第一个单链表的结点个数为a,第二个结点个数为b,相交部分结点个数为c
那么p1(==head1)走完整个单链表,走的距离为:a+c
那么p2(==head2)走完整个单链表,走的距离为:b+c
如果我们让p1走单链表的尾之后,从head2继续向后走,p2走到单链表的尾之后从head1继续向后走,那么最后p1和p2到相交的第一个结点一定相遇,因为它们俩这个时候走的总距离都为a+b+c+1,一起走的,所以p1和p2在单链表相交的第一个结点的位置一定相遇。如果单链表没有相交,那么最后p1和p2都会指向NULL。
在这里插入图片描述
代码:

ListNode* FindTheSameNode(ListNode* head1, ListNode* head2)
{
	if (head1 == NULL || head2 == NULL)
	{
		return NULL;
	}

	ListNode* p1 = head1;
	ListNode* p2 = head2;
	while (p1 != p2)
	{
		p1 = p1 == NULL ? head2 : p1->next;
		p2 = p2 == NULL ? head1 : p2->next;
	}
	return p1;//如果head1和head2相交,则p1(p2)为第一个相交的结点,如果不相交,那么p1 == p2 == NULL
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟小胖_H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值