环形链表的经典问题

环形链表

  • 环形链表的介绍
  • 链表中是否带环
  • 返回链表开始入环的第一个节点

本文主要介绍如何判断一个链表是否是环形链表,以及如何得到环形链表中的第一个节点。

环形链表的介绍

环形链表是一种链表数据结构,环形链表是某个节点的next指针指向前面的节点或指向自己这个节点的一个链表,这个链表就构成了环形链表。

链表中是否带环

要判断一个链表中是否带环,首先直接给出结论,我们可以用一个快指针(一次走两步),应该慢指针(一次走一步),如果该链表带环,最后快指针和慢指针就会在环中相遇,否则就是快指针走到空,这就表明该链表不带环。
判断一个链表是否带环Leetcode

根据这个思想,可以写出以下代码(快指针走两步,慢指针走一步):

bool hasCycle(struct ListNode *head) 
{if(head==NULL)return false;struct ListNode *slow=head;struct ListNode *fast=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast)return true;}return false;
}

分析:当链表为带环链表时,为什么快指针走两步,慢指针走一步就一定会在环中相遇?

当为环形链表时,快慢指针最总都会进入到环内。
在这里插入图片描述假设这个环是顺时针方向走的,当slow进入到带环的第一个节点,此时slow距离fast的节点个数为N,这个环的大小为C,示意图如上所示。fast走2步,slow走一步,那么两者之间的距离就会变成N-1,继续走就会变成N-2,N-3…,1,0.当两者之间的节点个数变为0那么就表示两者相遇了,这也可说明这个链表是带环的。所以当快指针走一步慢指针走两步(带环的链表),那么它们一定会在环中相遇。

如果快指针走三步,慢指针还是走一步那么它们是否还会再环中相遇吗?结论是它们也一定会在环中相遇。

在这里插入图片描述
假设这个环是顺时针方向走的,当slow进入到带环的第一个节点,此时slow距离fast的节点个数为N,这个环的大小为C,示意图如上所示。第一次fast走三步,slow走两步,这时两者之间的距离为N-2,继续走依次次为N-4…,当N为偶数是N-6,…,4,2,0。此时两者必定会在环中相遇。
当N为奇数时,两者之间的距离依次为N-6,…,5,3,1,-1。当为-1时表示fast追过了,其示意图如下:在这里插入图片描述
这就表示进行到了新一轮的追击中了,此时fast距离slow相差C-1个节点(从顺时针方向看),当C为奇数那么C-1就是偶数,那么距离的变化一定是C-3,…,4,2,0。所以此时一定也能相遇。
当C为偶数时,那就表示追不上,但是不存在这个情况(同时C为偶数并且N为奇数)。分析如下:
在这里插入图片描述
首先假设slow进环前走的距离为L,那么fast所走的距离为L+xC+C-N,其中x表示在环形链表中所转的圈数。又由于fast所走的距离为slow的三倍,所以有等式L+xC+C-N=3L,所以就有2L=(x+1)*C-N。左边等式一定是偶数,则右边也一定为偶数,假设C为偶数那么则N一定也是偶数,不然就不满足左边是偶数右边不是偶数了。只有当N为奇数,C为偶数才会永远无法再环中相遇,但这种情况不存在。 所以这也表示当fast走三步,slow走一步也一定会在环中相遇。

返回链表开始入环的第一个节点

返回链表开始入环的第一个节点Leetcode
使用快慢指针,快指针走两步慢指针走一步,它们两个一定会在环中相遇。此时一个从相遇点走,另一个从头节点开始走,两者同时走,当两者相遇时,这个相遇的节点就是入环的第一个节点。
根据这个思路代码如下:

struct ListNode *detectCycle(struct ListNode *head) 
{struct ListNode *slow=head;struct ListNode *fast=head;if(fast==NULL||fast->next==NULL)return NULL;struct ListNode *ret=NULL;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){ret=slow;break;}}if(!fast||!fast->next)return NULL;struct ListNode *cur=head;while(cur){if(cur==ret)return ret;cur=cur->next;ret=ret->next;}return NULL;
}

在这里插入图片描述

为什么一个从相遇点走,应该从头节点走,两者相遇的点就是环形链表环形的入口节点?

ret表示入环的第一个节点,meet表示快慢指针相遇点,head表示链表的头节点。环的大小为C,其示意图如上所示。慢指针到两者相遇所走的距离为L+C-N,快指针在两者相遇所走的距离为L+xC+C-N,由于快指针每次走两步,慢指针每次走一步,所以就有这个关系:2*(L+C-N)=L+xC+C-N,所以就有L=(x-1)C+N,其中x一定大于1。相遇点meet到环形入口节点的距离是N,而头节点到环形链表的入口节点距离是L,所以一个从相遇的节点开始走,另一个节点从头节点开始走,两者一定会在环形链表的入口节点相遇。

另一个思路就是通过寻找链表相交的第一个节点的思路:
依旧是通过快慢指针找到相遇点,再将相遇节点的next置空。这就相当于找链表第一个相交的节点了。
代码如下:

//找两个相交的链表struct ListNode *firstcrossnode(struct ListNode *head1,struct ListNode *head2) {if(head1==NULL)return NULL;if(head2==NULL)return NULL;int len1=0;int len2=0;struct ListNode *cur1=head1;struct ListNode *cur2=head2;while(cur1){cur1=cur1->next;len1++;}while(cur2){cur2=cur2->next;len2++;}int len=abs(len1-len2);struct ListNode *longlist=head1;struct ListNode *shortlist=head2;if(len1<len2){longlist=head2;shortlist=head1;}while(len--){longlist=longlist->next;}while(longlist){if(longlist==shortlist)return longlist;longlist=longlist->next;shortlist=shortlist->next;}return NULL;}
struct ListNode *detectCycle(struct ListNode *head) 
{struct ListNode *slow=head;struct ListNode *fast=head;if(fast==NULL||fast->next==NULL)return NULL;struct ListNode *meet=NULL;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){meet=slow;break;}}if(!fast||!fast->next)return NULL;struct ListNode*newhead=meet->next;meet->next=NULL;//将环形链表切割开struct ListNode* cur=head;//找第一个相交的链表struct ListNode*ret=firstcrossnode(cur,newhead);meet->next=newhead;//将链表还原回去return ret;
}

总结:本文主要介绍了两个环形链表的经典问题,判断一个链表是否是环形链表以及得到环形链表的入口节点,从公式推到到代码的实现。感谢大家观看,如有错误不足之处欢迎大家批评指针!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/5677.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ctfshow-web入门-102

这个题我想记录一下&#xff0c;主要是这个方法属实是有点惊艳到我了。故而进行记录&#xff0c;也为了方便大家阅读理解。 看题目&#xff0c;根据题目我写一下我的分析&#xff1a; $_POST传入一个v1&#xff0c;$_GET传入一个v2&#xff0c;一个v3。 赋值符号 优先级高于…

微软如何打造数字零售力航母系列科普05 - Azure中计算机视觉的视觉指南

Azure中计算机视觉的视觉指南 什么是计算机视觉&#xff1f;如何使用Microsoft Azure将计算机视觉功能集成到应用程序和工作流中&#xff1f; 作者&#xff1a;Nitya Narasimhan 编辑&#xff1a;数字化营销工兵 •11分钟阅读 什么是计算机视觉&#xff1f;如何使用Microso…

WORD排版常见问题与解决方案

前言 近期使用word软件进行论文排版工作&#xff0c;遇到了一些常见的问题&#xff0c;记录一下&#xff0c;避免遗忘。 基本配置 系统环境&#xff1a;win10/win11 word版本&#xff1a;Microsoft Office LTSC 专业增强版 2021 问题与解决方案 问题1&#xff1a;页眉显示内…

[华为OD]C卷 机场航班调度 ,XX市机场停放了多架飞机,每架飞机都有自己的航班号100

题目&#xff1a; XX市机场停放了多架飞机&#xff0c;每架飞机都有自己的航班号CA3385, CZ6678, SC6508 等&#xff0c;航班号的前2个大写字母&#xff08;或数字&#xff09;代表航空公司的缩写&#xff0c;后面4个数字代表航班信息。 但是XX市机场只有一条起飞用跑道&am…

【网络原理】IP协议的地址管理和路由选择

系列文章目录 【网络通信基础】网络中的常见基本概念 【网络编程】网络编程中的基本概念及Java实现UDP、TCP客户端服务器程序&#xff08;万字博文&#xff09; 【网络原理】UDP协议的报文结构 及 校验和字段的错误检测机制&#xff08;CRC算法、MD5算法&#xff09; 【网络…

LeetCode LCR 179. 和为s的两个数字

原题链接&#xff1a;LCR 179. 查找总价格为目标值的两个商品 - 力扣&#xff08;LeetCode&#xff09; 题目的意思&#xff1a;通过给定的数组&#xff0c;找出两个值&#xff0c;相加并等于目标值。 第一种思路&#xff0c;暴力枚举&#xff0c;伪代码如下&#xff1a; for (…

关于智慧校园,你知道多少?

智慧校园是指运用现代信息技术&#xff0c;如物联网&#xff08;IoT&#xff09;、大数据、云计算、人工智能&#xff08;AI&#xff09;等&#xff0c;对传统校园进行智能化改造和升级&#xff0c;旨在创建一个高度集成、信息共享、服务全面的校园生态系统。智慧校园不仅仅是技…

python web开发开源规范

Hello , 大家好。首先在五一假期给所有劳动者创造者们送上祝福&#xff0c; 本文聊聊我对python web开源相关的规范 PEP 8 Python编程风格指南:PEP 8是Python编程的官方风格指南&#xff0c;提供了关于代码格式、命名规范、注释等方面的建议。遵循PEP 8可以使代码更易于阅读和…

Gateway结合Nacos使用!!!

一、本地结合使用 1. 引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> 2. bootstarp.yml配置文件 如果Nacos中配置使用yaml格式&…

Dockerfile部署LNMP

目录 一、项目模拟 1. 项目环境 2. 服务器环境 3. 任务需求 二、Linux系统基础镜像 三、Nginx 1. 建立工作目录 2. 编写Dockerfile脚本 3. 准备nginx.conf配置文件 4. 生成镜像 5. 创建自定义网络 6. 启动镜像容器 7. 验证nginx 四、Mysql 1. 建立工作目录 2. …

19 做好微服务间依赖的治理和分布式事务

在前两讲里&#xff0c;分别从微服务的对外接口、消息消费以及微服务自身的相关编码规范上阐述了“防备上游、做好自己”这两个准则如何落地。 在本讲里&#xff0c;将会讲解为什么要“怀疑下游”&#xff0c;以及有哪些手段可以落地此条准则。此外&#xff0c;还会介绍在进行…

基于springboot实现迪迈手机商城设计系统项目【项目源码+论文说明】

基于springboot实现迪迈手机商城设计系统演示 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。…

Java面试重点之反射机制

一、 反射是什么&#xff1f; 允许程序在运行时查询和操作对象的类型信息。通过反射&#xff0c;程序能够在运行时获取对象的类定义信息&#xff0c;如类的名称、方法、字段、注解等&#xff0c;并且可以动态地调用对象的方法或访问其字段&#xff0c;而无需在编译时具体知道对…

编写你的第一个 golang 的应用程序

进行你的第一个golang的程序 当你把程序都安装好以后 环境变量配置 好 vscode 插件下载好以后 1. 创建一个test.go 的文件 //主包&#xff0c;可执行文件所在包 package main//导入包 import "fmt"//主函数&#xff0c;入口函数 func main() { }2.解释 需要导入包 …

WPF之border标签边框控件、设置弧度、图片

border标签在WPF中承担着边框的角色又称之为边框标签&#xff0c;使用嵌套的方法去给一些标签添加边框&#xff0c;border标签包裹目标标签(border不能有多个子元素)。一般在给标签添加弧度时可以使用border。 常用属性 CornerRadius边框拐角的弧度&#xff0c;当宽高是一样的…

Alibaba Cloud Linux 3.2104 LTS 64位安装mysql 8.0报错

问题描述 Alibaba Cloud Linux 3.2104 LTS 64位安装mysql 8.0提示 Error&#xff1a; GPG check FAILED 问题原因 官方 MySQL 存储库的 GPG 密钥已过期&#xff0c;无法安装或更新 MySQL 包 mysql官网也提交了该bug&#xff1a; https://bugs.mysql.com/bug.php?id106188 …

动态增删表格

期望目标&#xff1a;实现一个能通过按钮来动态增加表格栏&#xff0c;每次能添加一行&#xff0c;每行末尾有一个删减按钮。 <el-button type"text" class"primary"click"addMember()">添加</el-button> <el-table:data"m…

Pandas Series的运算原来这么简单

Series的运算主要包括加法、减法、乘法和除法等基本算术运算。这些运算通常是按照索引对应计算的&#xff0c;如果两个Series的索引不同&#xff0c;则结果中对应位置将填充为NaN&#xff08;空值&#xff09;。 需要注意的是&#xff0c;在进行Series运算时&#xff0c;需要确…

【linux】进程(深入理解linux进程状态)

开始之前先说一个与本文无关的小知识&#xff0c;chdir命令可以更改当前进程的工作目录哦。 目录 linux具体进程状态&#xff1a;R && S&#xff1a;T && t&#xff1a;D&#xff1a;僵尸进程 && 孤儿进程&#xff1a; OS的理论线&#xff1a;运行&…

讯饶科技 X2Modbus 敏感信息泄露

讯饶科技 X2Modbus 敏感信息泄露 文章目录 讯饶科技 X2Modbus 敏感信息泄露漏洞描述影响版本实现原理漏洞复现修复建议 漏洞描述 X2Modbus是一款功能很强大的协议转换网关&#xff0c; 这里的X代表各家不同 的通信协议&#xff0c;2是To的谐音表示转换&#xff0c;Modbus就是最…