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

相关推荐
张张努力变强3 小时前
C++ STL string 类:常用接口 + auto + 范围 for全攻略,字符串操作效率拉满
开发语言·数据结构·c++·算法·stl
万岳科技系统开发3 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
wWYy.3 小时前
数组快排 链表归并
数据结构·链表
张登杰踩3 小时前
MCR ALS 多元曲线分辨算法详解
算法
C++ 老炮儿的技术栈3 小时前
VS2015 + Qt 实现图形化Hello World(详细步骤)
c语言·开发语言·c++·windows·qt
YuTaoShao3 小时前
【LeetCode 每日一题】3634. 使数组平衡的最少移除数目——(解法一)排序+滑动窗口
算法·leetcode·排序算法
Once_day3 小时前
C++之《Effective C++》读书总结(4)
c语言·c++·effective c++
波波0073 小时前
每日一题:.NET 的 GC是如何分代工作的?
算法·.net·gc
风暴之零3 小时前
变点检测算法PELT
算法
深鱼~3 小时前
视觉算法性能翻倍:ops-cv经典算子的昇腾适配指南
算法·cann