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;
}

相关推荐
devilnumber1 小时前
Java 递归算法 详解 + 核心要点 + 实战运用 + 避坑指南
java·开发语言·算法
‎ദ്ദിᵔ.˛.ᵔ₎3 小时前
双指针、滑动窗口、前缀和、二分查找 算法
算法
顾北顾4 小时前
多头注意力机制
人工智能·深度学习·算法
H178535090964 小时前
SolidWorks_基于草图的实体特征20_特征错误排查
算法·3d建模·solidworks
hujinyuan201604 小时前
2025年12月中国电子学会青少年机器人技术等级考试试卷(二级) 真题+答案
人工智能·算法·机器人
玖玥拾4 小时前
C/C++ 基础笔记(十三)继承
c语言·c++·继承
bIo7lyA8v5 小时前
算法复杂度评估的实验统计方法与可视化的技术8
算法
李老师讲编程5 小时前
中国电子学会图形化2020.12月Scratch三级考级题
算法·scratch·信息学奥赛·图形化编程·scratch素材
退休倒计时5 小时前
【每日一题】LeetCode 53. 最大子数组和 TypeScript
数据结构·算法·leetcode·typescript