单链表有环求长度及相交问题

如何判断链表有环。如何计算环的长度。如何计算柄的长度 链表球环路的问题经常出现在面试题中,希望通过下面的解释能偶掌握这几个问题。 问题: 1、如何判断一个链表是不是这类链表? 2、如果链表为存在环,如何算环的长度? 3、如果链表为存在环,如何算柄的长度? 第一问是否有环就用快慢指针,fast=fast->next-next,slow=slow->next;代码如下 bool IsExitsLoop(slist *head) 阅读详情

单链表的节点只有一个指针指向下一个节点,两个单链表相交的话就会导致两个单链表的尾节点是相同的,所以只需要比较尾节点是否相同就可以知道两个单链表是否相交。但是,这样是否就完全没有问题了呢?

环!

其实不然,单链表有可能没有尾节点!为什么?因为有可能存在环!如果存在环的话上面那个办法就行不通了!考虑到因为环的存在,原来单链表的尾节点消失了,既然因为环没有尾节点了,那我们就创造一个尾节点!

假设两个单链表分别为A和B,第一步,遍历A,使用两个指针,一个指针每一步移动一个节点,另一个指针每一步移动两个节点(当然这里的一个节点和两个节点可以替换为别的数目,只要保证两个数的最大公约数为1就可以了,因为这个可以保证两个指针在环中一定会相遇)。使用两个指针遍历链表A,如果某一步两个指针相等,那么说明存在环,就将这一点作为A的尾节点,如果不存在环,我们最终也能获得A的尾节点。第二步,遍历链表B,并将每一个节点和A的尾节点相比较,如果存在相同的节点,那么说明两个链表相交,否则不相交。使用这种方法我们最终能在O(n+m)(n为A的长度,m为B的长度)的时间复杂度内解决问题。

环的长度怎么求?

如果知道链表A有环,那么怎么求出A的环的长度呢?这个问题其实非常简单!上文中已经描述了找到链表A的环中的一个节点,也就是那个尾节点,只要绕环一周便可以计算出环的 长度。

环的第一个节点?

如果链表有环,怎么求环的第一个节点呢?我在查阅资料的时候发现有这样一个定理:对于有环的单链表A,使用一个每次走一个节点的指针P和一个每次走两个节点的指针K遍历链表A,当指针P和K第一次碰撞时,此时用一个每次走一个节点的指针H从单链表头开始遍历,当指针P和H相遇时一定位于环的第一个节点!使用数学方法可以很容易来证明这个定理。设链表的节点为o1,o2,o3,……,oN,i1,i2,……,iK,……,iM其中o1是链表的第一个节点,oN是环的第一个节点,iK是指针P和K发生碰撞的节点(指针P和K发生碰撞的节点是唯一的),iM的next指针指向oN。当指针P和K第一次相遇时,此时指针P走过了N+K个节点,而指针K走过了2N+2K个节点,可以得到这样一个等式:N+K = N+((N+2K) mod (M+1)),化简可得:0 = (N+K) mod (M+1)!这个化简后的等式说明,指针P走过N个节点会处于oN节点,而指针H开始指向链表头,它走过N个节点也会位于oN节点,虽然不知到N究竟是多少,但是指针P和H同步走一定会相交于oN,而且相交的第一个位置就是oN。

链表的长度怎么求?

有了上一段的分析,链表的长度就容易得到了!有环的链表,其长度可以分为两部分来求,一部分是环外,一部是环!如果将无环链表看作是环长度为0的链表,则可以得到一个统一的求解链表长度的代码,见行93到125,其中,行99到106计算得到iK,行107到115计算环的长度,行116到122计算环外节点数目。

两个单链表的交点怎么求?

如果单链表不存在环,求解交点有两种比较好的方法,第一种方法是将链表尾节点指向其中一个链表的头节点,这样求交点的问题就转换成了求环的第一个节点问题,第二种方法效率更高一点,首先求出链表A和B的长度LA和LB,假设LA大于LB,将每次移动一个节点的指针PA指向链表A的第LA-LB+1个节点,将每次移动一个节点的指针PB指向链表B的第一个节点,然后同步移动指针PA和PB,两个指针相同时所指向的节点便是A和B的交点。如果单链表存在环的话,求解交点就麻烦一点,这里提一个比较简单的办法,对于链表A/B,取环上的第一个节点,将该节点指向链表B/A的头节点,这样得到一个新的有环链表,分别求解环的第一个节点,可以得到两个节点,如果两个节点相同,说明链表A和B的交点在环外,否则这两个链表在环外没有交点,这两个节点分别是链表A和B在环上的第一个节点!

下面贴上相关代码!

#include <iostream>
using namespace std;

struct list {
	int value;
	struct list *next;
};

struct list *insert(struct list *head, int v)
{
	if (head) {
		head->next = insert(head->next, v);
	} else {
		head = new struct list;
		head->value = v;
		head->next = 0;
	}
	return head;
}

void set_next_node(struct list *node, struct list *next)
{
	if (node) {
		node->next = next;
	}
}

struct list *find(struct list *head, size_t idx)
{
	while (idx-- && head && head->next) {
		head = head->next;
	}
	return head;
}

struct list *first_node(struct list *head1, struct list *head2)
{
	struct list *tail1, *next1 = 0;
	struct list *cursor1 = head1, *cursor2 = head1;
	do {
		if (cursor2) {
			cursor2 = cursor2->next;
			if (cursor2)
				cursor2 = cursor2->next;
		}
		tail1 = cursor1;
		next1 = cursor1->next;
		cursor1 = cursor1->next;
	} while (cursor1 != cursor2);
	cursor2 = head1;
	do {
		tail1 = cursor1;
		next1 = cursor1->next;
		cursor2 = cursor2->next;
		if (cursor1)
			cursor1 = cursor1->next;
	} while (cursor1 != cursor2);

	if (cursor1) {
		tail1 = cursor1;
		next1 = cursor1->next;
	}
	tail1->next = head2;

	cursor1 = head1, cursor2 = head1;
	do {
		if (cursor2) {
			cursor2 = cursor2->next;
			if (cursor2)
				cursor2 = cursor2->next;
		}
		cursor1 = cursor1->next;
	} while (cursor1 != cursor2);
	do {
		if (cursor2) {
			cursor2 = cursor2->next->next;
		}
		if (cursor1) {
			cursor1 = cursor1->next;
		}
	} while (cursor1 != cursor2);
	cursor2 = head1;
	do {
		cursor2 = cursor2->next;
		if (cursor1)
			cursor1 = cursor1->next;
	} while (cursor1 != cursor2);
	tail1->next = next1;

	return cursor1;
}

size_t length(struct list *head)
{
	size_t l = 0;
	if (head) {
		struct list *cursor1 = head;
		struct list *cursor2 = head;
		do {
			if (cursor2) {
				cursor2 = cursor2->next;
				if (cursor2)
					cursor2 = cursor2->next;
			}
			cursor1 = cursor1->next;
		} while (cursor1 != cursor2);
		do {
			if (cursor2) {
				cursor2 = cursor2->next->next;
			}
			if (cursor1) {
				l++;
				cursor1 = cursor1->next;
			}
		} while (cursor1 != cursor2);
		cursor2 = head;
		do {
			cursor2 = cursor2->next;
			if (cursor1)
				cursor1 = cursor1->next;
			l++;
		} while (cursor1 != cursor2);
	}
	return l;
}

void print_length(struct list *head, size_t l)
{
	cout << "list: ";
	while (head && l--) {
		cout << head->value;
		if (head->next) {
			if (l)
				cout << "->";
			else
				cout << "->[" << head->next->value <<"]";
		}
		head = head->next;
	}
	cout << endl;
}

void print(struct list *head)
{
	print_length(head, length(head));
}

int main()
{
	struct list *head1 = 0;
	struct list *head2 = 0;
	head1 = insert(head1, 0);
	head1 = insert(head1, 1);
	head1 = insert(head1, 2);
	head1 = insert(head1, 3);
	head1 = insert(head1, 4);
	head1 = insert(head1, 5);
	head1 = insert(head1, 6);
	head1 = insert(head1, 7);
	head1 = insert(head1, 8);
	head1 = insert(head1, 9);
	head2 = insert(head2, 10);
	head2 = insert(head2, 11);
	head2 = insert(head2, 12);
	head2 = insert(head2, 13);
	set_next_node(find(head1, -1), find(head1, 4));
	set_next_node(find(head2, -1), find(head1, 6));
	print(head1);
	print(head2);
	cout << length(head1) << endl;
	cout << length(head2) << endl;
	cout << "node: " << first_node(head1, head2)->value << endl;
	cout << "node: " << first_node(head2, head1)->value << endl;
	return 0;
}

如何判断单链表是否有环、环的入口、环的长度和总长 问题描述1.如何判断单链表是否有环? 2.如果有环,求出环的入口 3.求环长 4.求总长注意这里长度:节点的数量 链表定义参考:http://blog.youkuaiyun.com/dawn_after_dark/article/details/73610674探讨要想判断有环,我们可以联系实际生活中的例子,很容易就想到操场上跑圈,因为是环形,所以快的肯定会追上慢的,所以我们可以应用到链表上,用一个快指 阅读详情

相关推荐

求单链表交点

本文首发在我的个人博客:https://jlice.top/p/7qhfm/。欢迎大家前去参观,么么哒~ 题目 今天面试时,面试官问了这样一个问题:两个单链表相交,怎么求交点。所谓相交,就是两个节点的next指针相同。 简单解法 一个简单的思路是:分别遍历这两个链表,并将这两个链表的节点分别保存到两个列表里,然后同步逆序遍历这两个列表,当出现不相同的元素时,则下一个元素就是这两个链表的交...

文剑木然的专栏 1139

【刷题篇】链表(下)

🌸各位读者们好,本期我们来填填之前留下的坑,继续来讲解几道和链表相关的OJ题。但和上期单向链表不一样的是,我们今天的题目主要是于环形链表有关,下面让我们一起看看吧。💻环形链表环形链表II求环形链表环长环形链表💍。

忆梦初心的博客 3201

耶鲁大学《博弈论》课程——逆向归纳

耶鲁大学《博弈论》课程——逆向归纳

ZYLer_的博客 7871

求有环单链表中的环长、环起点、链表长

1.判断单链表是否有环 使用两个slow, fast指针从头开始扫描链表。指针slow 每次走1步,指针fast每次走2步。如果存在环,则指针slow、fast会相遇;如果不存在环,指针fast遇到NULL退出。 就是所谓的追击相遇问题: 2.求有环单链表的环长 在环上相遇后,记录第一次相遇点为Pos,之后指针slow继续每次走1步,fast每次走2步。在下次相遇的时候fast比slow正好又多走了一圈,也就是多走的距离等于环长。 设从第一次相遇到第二次相遇,设slow走了len步,则fast走了2*le

昔拉的博客 820

Burp靶场实战:JWT签名绕过漏洞分析与利用

本文通过Burp Suite靶场实战,深入剖析了JWT签名绕过漏洞的多种攻击手法,包括签名未验证、alg:none攻击、弱密钥爆破、JWK/JKU头注入、KID路径遍历及算法混淆攻击。文章详细演示了利用过程,并提供了关键的防御指南,帮助开发和安全人员加固JWT实现,确保认证安全。

weixin_29325515的博客 594

高效搭建微信公众号爬虫全流程

微信公众号爬虫系统成功完成功能测试验证。该系统具备完整的数据采集与管理能力,支持多公众号内容爬取、数据存储与统计分析。通过命令行界面可执行爬取操作(如量子位、新智元等公众号),查看最新文章列表和系统统计信息。测试显示SQLite数据库正常存储数据,所有核心功能(多源支持、文章检索、数据统计)均运行良好。系统采用模块化设计,扩展性强,为后续接入真实API或网页爬取奠定了坚实基础,是AI内容聚合的优质开发平台。🎉

weixin_44975687的博客 1554

关于链表有环的扩展问题:求环的长度和入环节点

一、求环的长度 二、求入环节点 一、求环的长度 解法:当两个指针首次相遇,说明链表有环,让两个指针从相遇点继续循环前进,并统计前进的次数,直到两个指针再次相遇。具体可参考如下公式: 环长=每一次速度差 X 前进次数 代码实现: class Node: def __init__(self,data): self.data=data self.next=None def isCycle(head): p1=head p2=head flag=Fa

weixin_43300894的博客 632

Solidworks二次开发(C# .NET API):从零构建装配体与虚拟零件

本文详细介绍了使用C#进行Solidworks二次开发,从零构建装配体与虚拟零件的完整流程。通过.NET API实现设计自动化,涵盖环境搭建、核心对象模型、虚拟零件创建与外部化保存等关键技术,帮助工程师将重复性建模工作程序化,大幅提升设计效率与标准化水平。

alice7model的博客 607

单链表有环的几个问题

转自:https://www.cnblogs.com/dancingrain/p/3405197.html 给定一个单链表,判断其中是否有环,已经是一个比较老同时也是比较经典的问题,在网上搜集了一些资料, 然后总结一下大概可以涉及到的问题,以及相应的解法。 首先,关于单链表中的环,一般涉及到一下问题: 1.给一个单链表,判断其中是否有环的存在; 2.如果存在环,找出环的入口点; 3.如果存在环,求出环上节点的个数; 4.如果存在环,求出链表的长度; 5.如果存在环,求出环上距离任意一个.

wanlong1215的博客 353

图像处理(12)--图像各种噪声及消除方法

文章目录结构1.什么是图像噪声2. 图像噪声来源3. 噪声分类及其消除方法3.1 高斯噪声及其消除方式3.1.1 如何确定一种噪声是高斯噪声3.1.2 高斯滤波消除高斯噪声3.1.3 高斯函数的重要性质3.2 瑞利噪声及其消除方式3.3 伽马(爱尔兰)噪声及其消除方式3.4 指数分布噪声及其消除方式3.5 均匀噪声及其消除方式3.6 脉冲(椒盐)噪声及其消除方式 1.什么是图像噪声 图像噪声是指...

ShaneHolmes 11万+

Simplorer-Maxwell联合仿真速度太慢?我用这3个技巧把仿真时间砍半(附SVPWM周期与步长设置避坑)

本文详细介绍了Simplorer-Maxwell联合仿真性能优化的3个关键技巧,包括仿真步长与周期的科学配置、基于任务调度的加速技术以及模型简化与精度平衡。特别针对SVPWM参数设置提供了避坑指南,帮助工程师在不牺牲精度的情况下将仿真时间缩短50%以上,适用于电机驱动系统开发等场景。

weixin_29189381的博客 466

单链表的相交问题

链表相交问题

zyl_1102179268的博客 674

PnP 单目相机位姿估计(二):solvePnP利用二维码求解相机世界坐标

前言 原理简介 输入参数准备 1 objectPoints特征点世界坐标 2 imagePoints特征点在摄像头下的像素点坐标 3cameraMatrixdistCoeffs内参矩阵和畸变矩阵 相机世界坐标的求解 1求世界坐标中的点在相机坐标系下的坐标 2求相机在世界坐标中的坐标 3效果求解相机在世界坐标系下的坐标点 4求解代码1.前言  很多时候,当我们利用单目相机获取图像时,往往只能获取图像中

cocoaqin的博客 5万+

单链表算法二-----含环的单链表

Node *IsCircle(List plist) { Node *quick = plist; Node *slow = plist; while (quick != NULL && quick->next != NULL) { quick = quick->next->next; slow ...

qq_41052753的博客 263

uniapp - 解决在线预览PDF文件空白打不开的问题,无论是后端下载二进制文件流pdf还是本地插件或JS预览查看打开白屏不显示,详细排查解决(适用于移动端H5网页、安卓/苹果app、微信小程序)

uniapp App端 实现pdf文件预览打开白屏解决,uniapp 在线预览pdf打开一片空白,跨域白屏,uni-app中使用WebView预览PDF文件打开空白,微信小程序(uniapp)预览PDF空白怎么办,下载PDF文件流后打开空白或无法打开的问题,Uniapp H5网页下载二进制pdf文件页面空白以及解决文件损坏打不开的情况,Uniapp app在线预览pdf文件流,PDF加载出来怎么办,服务器后端返回PDF文件流后前端进行下载但打开后一片白屏,解决pdf文件流,预览全是空白页,pdf文件流,下载

🏆 前端领域优质创作者 1万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

单向链表环相关问题

目录 一、判断单链表中是否有环 二、求有环单链表的环长 三、求有环单链表的环起点 四、求有环单链表的链表长度 五、代码实现 六、确定两个单向链表是否相交 核心:快慢指针(fast每次2步、slow每次1步) 参考 -1- - 2- 一、判断单链表中是否有环 使用两个指针从头开始扫描链表。 如果存在环,则两指针会相遇;如果不存在环指针fast遇到NUL...

来啦(#^.^#) 399

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

单链表带环问题

判断单链表是否带环?若带环,求环的长度?求环的入口点?  1 2 3 4 5 6 7 8 9 不带环: 链表遍历一次, 到最后的节点的下一个节点会指向NULL,此时链表不带环。 带环: ,在判断链表是否带环之前,应该先判断链表是否为空。空链表肯定不带环。只要链表带环,对链表进行遍历就会形成死循环,没有出口。这是就需要用到快慢指针来确定链表是否带环。 定义两个指针(fas

liuxiaokai_liu的博客 457

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

单链表中环的问题

给定一个单链表,判断其中是否有环,已经是一个比较老同时也是比较经典的问题,在网上搜集了一些资料, 然后总结一下大概可以涉及到的问题,以及相应的解法。 首先,关于单链表中的环,一般涉及到一下问题: 1.给一个单链表,判断其中是否有环的存在; 2.如果存在环,找出环的入口点; 3.如果存在环,求出环上节点的个数; 4.如果存在环,求出链表的长度; 5.如果存在环,求出环上距离任意一个节点...

AcceptedLin的博客 313

单链表的几道经典面试题(2)

1.判断单链表是否带环2.计算环的长度3.求环的入口4.判断两个链表是否相交,若相交求交点(默认链表不带环)5.判断两个链表是否相交,若相交求交点(链表可能带环)6.找两个已排序链表的相同部分7.复杂链表拷贝判断单链表是否带环方法一:将每个节点保存到顺序表中,再将每个节点遍历,看是否带环。但是这种方法的时间复杂度为O(n^2),所以,又想出了一种方法,来优化第一种方法,来使时间复杂度变为O(n)方...

L_X_Y_HH的博客 275

9判断两个单链表是否相交

//单链表交换任意两个元素(不包括表头) #include using namespace std; struct LinkNode { LinkNode *pNext; int nValue; LinkNode(int value = 0) { nValue = value; pNext = NULL; } }; class Linklist { public: Lin

u012713968的专栏 550

基于ADS122U04与PIC18F4685的高精度PT100温度采集方案

温度感知是工业自动化和楼宇自控中最基础也最关键的环节。PT100铂电阻因精度高、稳定性好被广泛使用,但其阻值随温度变化产生的信号极其微弱,普通MCU内置ADC的分辨率和抗干扰能力难以满足现场需求。采用带可编程增益放大器和恒流源的高分辨率24位Δ-Σ ADC,配合独立MCU进行数据换算与通信,才能从硬件层面保障测量稳定性。ADS122U04IPWR作为带UART接口的24位ADC,集成PGA、参考源和IDAC激励源,非常适合PT100/RTD的小信号采集;PIC18F4685则提供CAN等总线接口,便于构建分

weixin_30843605的博客 212

C语言面试题进阶篇

1.判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法的时间复杂度&空间复杂度。 首先判断是否带环,在这里用快慢指针,快指针每次走两步,慢指针每次只走一步,无环的快指针会先走到头,如果快指针等于慢指针那么说名单链表存在环,会返回相遇点,如果无环会返回空指针。为什么一个走两步一个走一步就可以呢,因为fast比slow走的快,所以进入环是fast一定在slow前面(或相遇),假设领

T_tangcのblog 665

C语言的单链表面试题----进阶

题目 判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法的时间复杂度&空间复杂度。判断两个链表是否相交,若相交,求交点。(假设链表不带环)判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】 求带环链表环长 (无环返回 -1) 思路 快慢指针法,快指针一次走两步,慢指针一次走一步,如果链表带环,则从慢指针到达入口点开始,由于快慢指针都

ZoctopusD的博客 510

链表经典面试题三

题型十一:判断单链表是否带环,若带环,求出环的长度,环的入口点, 1、判断是否带环: 判断一个链表是否带环的带环的条件是,当链表不带环时尾节点指向空,当链表带环时,链表没有尾节点。 ListNode* IsCycle(ListNode* pHead)//判断链表是否带环,若带环,返回快慢指针相遇的节点 { ListNode* cur = pHead; ListNode...

ffsiwei的博客 646

【数据结构】单链表--进阶题目

在实现单链表的基本与基础的操作后:   我们可以在单链表中考虑环与相交以及复杂单链表的问题。 1.判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法的时间复杂度&空间复杂度:   ListNode* IsCycle(ListNode *pList)//是否带环 { if ((pList == NULL) || (pList->next == NULL)) return

LazyFish的博客 507
上一篇: 几个字符串匹配算法
下一篇: 找出二叉树中和为某值的所有路径
notishell
博客等级 码龄15年 0粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值