C语言-数据结构-相交链表

文章讲述了如何在给定两个单链表的头节点的情况下,找到它们相交的起始节点,若无交点则返回null。介绍了两种思路,其中详细阐述了使用思路2,即利用链表长度差异求解相交问题的算法实现和测试过程。
摘要由CSDN通过智能技术生成

给定两个单链表的头节点 headA 和 headB ,请找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

提示:

  • listA 中节点数目为 m
  • listB 中节点数目为 n
  • 0 <= m, n <= 3 * 104
  • 1 <= Node.val <= 105
  • 0 <= skipA <= m
  • 0 <= skipB <= n
  • 如果 listA 和 listB 没有交点,intersectVal 为 0
  • 如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]

此题因为是链表,所以两个链表一旦相交,就意味着交点的地址是一样的,并且其后面的节点的地址也都是一样的

两种思路:

思路1:(暴力求解)
  依次取A链表中的每一个节点与B链表中的每一个节点进行比较,如果有地址相同的节点,则返回该节点;如果遍历完A链表中的所有节点都没有找到相交节点,则返回null;
思路2:
  尾结点相同就是相交,尾结点不同,就不相交
  求交点:长的链表先走(长度差)步,再同时走,第一个相同的就是交点

以下代码为思路二的方法:

因为要考虑到两个链表在相交前有可能长度不一样,所以我们要判断哪个链表长,长多少,让长的链表先走相差的步数,然后在一起走。

这里用到了一个abs的函数求差值的绝对值。

对于判断哪个链表长,这里用了一个巧方法:

先假设A链表为长链表,B链表为短链表,然后判断A链表与B链表的长度,如果A链表长度小于B链表的长度,那就假设错误,将B链表重新改为长链表,A链表重新改为短链表,后面便只要用长链表和短链表来用就行了。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    	//找尾部节点,求长度
	struct ListNode * tailA = headA;
	int lenA = 1;
	struct ListNode * tailB = headB;
	int lenB = 1;
	while (tailA->next)
	{
		lenA++;
		tailA = tailA->next;
	}
	while (tailB->next)
	{
		lenB++;
		tailB = tailB->next;
	}
	//判断是否相交
	if (tailA != tailB)
	{
		return NULL;
	}
		int gap = abs(lenA - lenB);
	//长的先走差距步,再同时走找交点
	struct ListNode * longList = headA;
	struct ListNode * shortList = headB;
	if (lenA < lenB)
	{
		longList = headB;
		shortList = headA;
	}
	while (gap--)
	{
		longList = longList->next;
	}
	while (longList != shortList)
	{
		longList = longList->next;
		shortList = shortList->next;
	}
	return longList;
}

测试函数:

void test(struct ListNode* plist1, struct ListNode* plist2)
{
	struct ListNode* inter_node = getIntersectionNode(plist1, plist2);
	if (inter_node)
	{
		printf("相交节点为:%d\n", inter_node->val);
	}
	else
	{
		printf("两个链表没有交点\n");
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值