OJ12:160. 相交链表

目录


题目

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

示例 1

输入 :intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出 :Intersected at '8'
解释 :相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。

从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。

在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

--- 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。
示例 2

输入 :intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出 :Intersected at '2'
解释 :相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。

从各自的表头开始算起,链表 A 为 [1,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
输出 :No intersection
解释 :从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。

由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。

这两个链表不相交,因此返回 null 。

思路分析

我们想要找到是否相交,就要找出指向相等的地址的节点·,这样就可以找到其相交的节点;

  1. 由于我们不知道两个链表的长度如何,所以我们要对较长的那个链表 "先走差距步"保证两个链表长度相等了之后,再移动。
    这样我们就要先算出两个链表的长度进行比较:
c 复制代码
//计算两个链表的长度
int la = 0;
int lb = 0;
ListNode* curA = headA;
ListNode* curB = headB;

while (curA)
{
	la++;
	curA->next;
}
while (curB)
{
	lb++;
	curB->next;
}
  1. 确定长链表,但是我们无法确定那个是长链表,所以我们假设A链表是长链表,如果不是,我们再作交换:
c 复制代码
//假设headA指向的链表长
ListNode* longNode = headA;
ListNode* shortNode = headB;
if (la < lb)  //假设不成立
{
	longNode = headB;
	shortNode = headA;
}
  1. 移动长链表的指针,使指针后的两个链表的节点个数一致
c 复制代码
int gap = abs(la - lb);
while (gap--)
{
	longNode = longNode->next;
}

4. 共同向后移动,直到找到指向相同的节点

c 复制代码
while (longNode)
{
	if (longNode == shortNode)
		return longNode;
	longNode = longNode->next;
	shortNode = shortNode->next;
}
return NULL;


代码展示

c 复制代码
struct ListNode {
    int val;
    struct ListNode* next;
};
typedef struct ListNode ListNode;
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) {
	if (headA == NULL || headB == NULL)
		return NULL;
	//计算两个链表的长度
	int la = 0;
	int lb = 0;
	ListNode* curA = headA;
	ListNode* curB = headB;

	while (curA)
	{
		la++;
		curA->next;
	}
	while (curB)
	{
		lb++;
		curB->next;
	}

	//假设headA指向的链表长
	ListNode* longNode = headA;
	ListNode* shortNode = headB;
	if (la < lb)  //假设不成立
	{
		longNode = headB;
		shortNode = headA;
	}

	int gap = abs(la - lb);
	while (gap--)
	{
		longNode = longNode->next;
	}

	while (longNode)
	{
		if (longNode == shortNode)
			return longNode;
		longNode = longNode->next;
		shortNode = shortNode->next;
	}
	return NULL;
}

相关推荐
沐怡旸15 小时前
【算法】【链表】328.奇偶链表--通俗讲解
算法·面试
掘金安东尼18 小时前
Amazon Lambda + API Gateway 实战,无服务器架构入门
算法·架构
码流之上19 小时前
【一看就会一写就废 指间算法】设计电子表格 —— 哈希表、字符串处理
javascript·算法
用户61204149221320 小时前
C语言做的文本词频数量统计功能
c语言·后端·敏捷开发
快手技术21 小时前
快手提出端到端生成式搜索框架 OneSearch,让搜索“一步到位”!
算法
CoovallyAIHub2 天前
中科大DSAI Lab团队多篇论文入选ICCV 2025,推动三维视觉与泛化感知技术突破
深度学习·算法·计算机视觉
NAGNIP2 天前
Serverless 架构下的大模型框架落地实践
算法·架构
moonlifesudo2 天前
半开区间和开区间的两个二分模版
算法
moonlifesudo2 天前
300:最长递增子序列
算法
CoovallyAIHub2 天前
港大&字节重磅发布DanceGRPO:突破视觉生成RLHF瓶颈,多项任务性能提升超180%!
深度学习·算法·计算机视觉