环形链表的经典问题

环形链表

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

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

环形链表的介绍

环形链表是一种链表数据结构,环形链表是某个节点的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。 赋值符号 优先级高于…

vue和react这两大前端框架的优缺点对比

【A】Vue和React是目前最流行的两个前端框架&#xff0c;它们都具有各自的优点和缺点。下面是对Vue和React的优缺点的详细介绍&#xff1a; Vue的优点&#xff1a; 简单易学&#xff1a;Vue的API设计简单&#xff0c;上手较为容易&#xff0c;学习曲线相对较低。文档丰富&…

微软如何打造数字零售力航母系列科普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;页眉显示内…

SQL数据库经典题型(2)列出有二门以上(含两门)不及格课程的学生姓名及其平均成绩

1.查询平均成绩不及格的学生姓名及平均成绩 select s1.s_id,s1.s_name,round(avg(s2.s_score)) from s_student s1,s_score s2 where s1.s_ids2.s_id group by s1.s_id,s1.s_name having round(avg(s2.s_score))<60; 2.--列出有二门以上&#xff08;含两门&#xff09;不…

SSH远程Ubuntu22.04无法通过X11转发xclock之外的其他GUI界面

问题前置条件 ssh远程Ubuntu22.04服务器开发环境无异常x11转发环境已配置&#xff0c;xclock可正常运行于本地环境可视化程序能够正常运行于Linux服务器 问题现象 除xclock等x11验证工具外&#xff0c;其他诸如python之类编写的可视化程序均无法透过X11转发至本地环境 问题…

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

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

Apollo 编译时报错 ERROR: Config value ‘gpu‘ is not defined in any .rc file

用Apollo的某个版本的源码&#xff0c;执行 bash docker/scripts/dev_start.sh bash docker/scripts/dev_into.sh 创建容器并进入容器后执行 bash apollo.sh build_gpu 编译报错: WARNING: The following rc files are no longer being read, please transfer their conten…

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

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

leetcode 搜索插入位置

给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2示例 2: 输入…

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

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

在C#中使用s7Netplus实现与西门子PLC的数据通信

在C#中使用s7Netplus实现与西门子PLC的数据通信 S7.Net Plus&#xff08;简称s7Netplus&#xff09;是一个开源的西门子PLC驱动程序&#xff0c;专为通过以太网连接与西门子PLC进行通信而设计。它完全用C#编写&#xff0c;使得开发者能够在不处理本地DLL的情况下轻松地进行调试…

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

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

python web开发开源规范

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

华为校招机试 - 找到内聚值最大的微服务群组(20240424)

题目描述 开发团队为了调研微服务调用情况,对 n 个微服务调用数据进行了采集分析,微服务使用数字 0 至 n-1 进行编号。 给你一个下标从 0 开始的数组 edges,其中 edges[i] 表示存在一条从微服务 i 到微服务 edges[i] 的接口调用。 我们将形成 1 个环的多个微服务称为微服…

Docker:学习笔记【1】

文章目录 Docker简介Docker基本使用步骤Docker局限性Docker主要概念镜像与容器DockerHubDocker架构Docker与虚拟机参考链接Docker简介 Docker 是一个开源的容器化平台,可以帮助开发者将应用程序及其依赖项封装为一个可移植的容器,然后可以在不同的环境中运行。Docker利用容器…

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. …

使用zookeeper作为分布式节点的配置中心

安装 wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.9/zookeeper-3.4.9.tar.gz tar xfzv zookeeper-3.4.9.tar.gz && mv zookeeper-3.4.9/conf/zoo_sample.cfg zookeeper-3.4.9/conf/zoo.cfg vim zoo_sample.cfg zookeeper-3.4.9/conf/zoo.cfg 把dat…

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

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