【刷题篇】链表(下)

news2025/7/5 23:15:12
  1. 前言🌸

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

💻本期的题目有: 环形链表环形链表II求环形链表环长
  1. 环形链表💍

a.题目

b.题解分析

第一种方法,我们可以遍历链表,使用哈希表来保存已经经过的结点。每次经过一个结点时,通过哈希表判断结点是否被访问过,如果有,则说明存在环;如果没有则继续访问下一结点,以此循环直到遍历完整个链表。这样的时间复杂度为O(N),空间复杂度为O(N),不满足题目的进阶解法

第二种方法,我们可以使用上期学习的快慢指针法定义步长为2的快指针和步长为1的慢指针遍历链表。我们假设链表如果存在环,则快慢指针在某一时刻一定会在环内相遇;而如果不存在环,由于快指针速度比慢指针快,因此它们永远无法相遇。动态效果如下:

我们可以看到如果链表存在环时, 当慢指针进入环中后,快指针就会开始绕环追逐慢指针。我们假设此时快慢指针距离为n,由于 v(快)-v(慢)=1,则每次行动快慢指针的距离就会缩短1, 行动n次后快慢指针一定就会相遇。因此我们可以通过判断是否相遇来判断是否有环。

c.AC代码

struct ListNode
{
    int val;
    struct ListNode* next;    
};
bool hasCycle(struct ListNode* head) 
{
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while (fast && fast->next) //当到达或即将到达链表尾时退出循环
    {
        //快慢指针移动
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow)
        {
            return true; //相遇
        }
    }
    return false; //没有相遇、没有结点、只有一个结点且非循环,不存在环

}

d.拓展思考

通过以上例子,我们知道 速度差为1快慢指针可以用来判断链表是否存在环。那么, 速度差为2的是不是也可以用来判断呢?速度差为3的呢?为n的呢?

我们来分析一下:当快慢指针的速度差为2时,假设慢指针进入环时快指针与其距离为n,环的总长为m,如下:

由于它们的速度差为2,则每次行动后n=n-2。我们很容易发现,如果n为偶数时,当行动次后快慢指针就会相遇;但是当n为奇数时,最后快慢指针就会错过,进入下一轮追赶中。而在第二轮追赶开始时,快慢指针距离为m-1,假如m-1又是奇数,则本轮又会错过进而进入第三轮追逐。然后第三轮开始时依旧相距m-1,又会错过,以此反复......,最后永远不会相遇(史上最遥远的距离,无非就是我在你身旁,你却不理不睬😭)因此,使用速度差为2的快慢指针,不能保证是否可以判断出某个链表是否存在环,速度差为3,为n的同理

  1. 环形链表 II✈

a.题目

b.题解分析

我们同样可以在上一题的基础上使用快慢指针来求解。

我们假设链表头到环入口的长度为S,环的长度为C。当慢指针走到环入口,此时快指针的位置和慢指针的位置关系如下:

我们假设此时快慢指针的距离为L,这里可能有读者有疑问:快指针是慢指针速度的2倍,那L的大小不应该是S吗?实际上,当slow到达环入口时,fast可能已经绕环n圈了,所以fast实际走过的长度共为S+nC+L()。由此我们可以得出S+nC+L=2S,即L=S-nC在这之后,快指针开始追逐慢指针,我们假设在如下位置相遇:

假设共进行了D次追逐才追上了慢指针,由快指针比慢指针快一倍可以得出以下关系:

因此,相遇点到快指针最初位置的距离为S-nC-D,由此可以得出相遇点到环结点的距离为S-nC-D+D=S-nC,如下:

至此,我们发现链表头到环入口的距离S与相遇点到环入口的距离S-nC相差n个环的长度

由此我们算法的思路是:

起初快指针速度为2,慢指针速度为1,如果快慢指针没有相遇,则返回NULL代表不存在环;如果相遇了,我们就让 其中一个指针重新指向链表头,并使 两个指针的速度都为1,一直前进直到它们相遇,相遇的位置一定为环的位置。这是因为从 相遇点走S步后的位置与走S-nC步后的位置一致

c.AC代码

struct ListNode {
    int val;
    struct ListNode* next;
};
struct ListNode* detectCycle(struct ListNode* head)
{
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while (fast && fast->next) //当到达或即将到达链表尾时退出循环
    {
        //快慢指针移动
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow) //相遇,存在环
        {
            //两个指针找环入口
            slow = head;
            while (slow!=fast)
            {
                slow = slow->next;
                fast = fast->next;
            }
            return slow;
        }
    }
    return NULL;//没有相遇、没有结点、只有一个结点且非循环,不存在环,返回空

}    
  1. 求环形链表的环长💫

a.题目

给定一个链表的头节点 head ,返回链表环中环的长度。 如果链表无环,则返回 0。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。

b.题解分析

法一:我们同样可以先使用快慢指针判断链表是否存在环,当二者第一次相遇时说明链表存在环。而当快慢指针相遇后我们再次让快慢指针进行追逐战,此时它们之间的距离为环长C,由于每次追逐它们的距离都会缩短1,因此我们可以定义一个计数器count记录第二次相遇时所追逐的次数即为链表的环长。具体过程如下:

c.AC代码

 struct ListNode {
    int val;
    struct ListNode* next;
    
};
int CycleLength(struct ListNode* head)
{
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while (fast && fast->next) //当到达或即将到达链表尾时退出循环
    {
        //快慢指针移动
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow) //第一次相遇,存在环
        {
            //统计第二次相遇所追逐的次数
            int count = 0;
            do
            {
                fast = fast->next->next;
                slow = slow->next;
                count++;
            } while (fast != slow);
            //相遇了,返回追逐次数即为环长
            return count;
        }
    }
    //不存在环,返回0
    return 0;

}

以上,就是本期的全部内容啦🌸

制作不易,能否点个赞再走呢🙏

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

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

相关文章

vue3-element-admin搭建

vue3-element-admin 是基于 vue-element-admin 升级的 Vue3 Element Plus 版本的后台管理前端解决方案,是 有来技术团队 继 youlai-mall 全栈开源商城项目的又一开源力作功能清单技术栈清单技术栈 描述官网Vue3 渐进式 JavaScript 框架 https://v3.cn.vuejs.org/Ty…

IDEA 开发一个简单的 web service 项目,并打包部署到 Tomcat

文章目录实现的效果一、创建 web service 项目二、测试类运行 web service 服务端三、IDEA 打包 web service 项目四、web service 项目部署到 Tomcat五、web service 客户端总结实现的效果 通过 IDEA 创建一个简单的 web service 项目 用测试类运行这个 web service 项目 通…

软件测试面试-一线大厂必问的测试思维面试题

五、测试思维5.1 打电话功能怎么去测?我们会从几个方面去测试:界面、功能、兼容性、易用性、安全、性能、异常。1)界面我们会测试下是否跟界面原型图一致,考虑浏览器不同显示比例,屏幕分辨率。2)功能&#…

【Linux】环境变量,命令行参数,main函数三个参数保姆教学

目录 ☃️1.奇奇怪怪的现象和孤儿进程 ☃️2.环境变量 ☃️3.深刻理解main函数的前两个参数和命令行参数 ☃️1.奇奇怪怪的现象和孤儿进程 首先回顾一下之前我们学过的fork()创建子进程 fork(void)的返回值有两种 注意fork()头…

C#:Krypton控件使用方法详解(第八讲) ——kryptonBreadCrumb

今天介绍的Krypton控件中的kryptonBreadCrumb,下面开始介绍这个控件的属性:首先要介绍的是RootItem属性和外观属性:RootItem属性组中包含属性如下:image属性:代表在文字对象的前方插入一个图片,属性值如下图…

多元化业务布局全面开花,松井股份有望步入高成长正轨

2022年,宏观经济下行压力加大、疫情反复不断、国内消费需求不足等诸多因素,导致国内涂料行业遭遇“至暗时刻”,企查查平台数据显示,2022年1-10月,破产重整、注销拍卖的涂料企业超过700家。2月11日,国内涂料…

使用 PyTorch+LSTM 进行单变量时间序列预测(附完整源码)

时间序列是指在一段时间内发生的任何可量化的度量或事件。尽管这听起来微不足道,但几乎任何东西都可以被认为是时间序列。一个月里你每小时的平均心率,一年里一只股票的日收盘价,一年里某个城市每周发生的交通事故数。 在任何一段时间段内记…

代码随想录算法训练营第四天 | 链表理论基础、4. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

打卡第四天,因为科三前几天没有带电脑,现在重新补一下第四天的卡 今日任务 24. 两两交换链表中的节点19.删除链表的倒数第N个节点面试题 02.07. 链表相交142.环形链表II 24. 两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点&#…

C++类和对象_02----对象模型和this指针

目录C对象模型和this指针1、成员变量和成员函数分开存储1.1、空类大小1.2、非空类大小1.3、结论2、this指针概念2.1、解决名称冲突2.2、在类的非静态成员函数中返回对象本身,可使用return *this2.3、拷贝构造函数返回值为引用的时候,可进行链式编程3、空…

Python加密算法种类以及开发场景中的运用

不用说火爆一时,全网热议的Web3.0区块链技术,也不必说诸如微信支付、支付宝支付等人们几乎每天都要使用的线上支付业务,单是一个简简单单的注册/登录功能,也和加密技术脱不了干系,本次我们耙梳各种经典的加密算法&…

【RecBole-GNN/源码】RecBole-GNN中lightGCN源码解析

如果觉得我的分享有一定帮助,欢迎关注我的微信公众号 “码农的科研笔记”,了解更多我的算法和代码学习总结记录。或者点击链接扫码关注【RecBole-GNN/源码】RecBole-GNN中lightGCN源码解析 【RecBole-GNN/源码】RecBole-GNN中lightGCN源码解析 原文&…

【C++】初识CC++内存管理

前言 我们都知道C&C是非常注重性能的语言,因此对于C&C的内存管理是每一个C/C学习者必须重点掌握的内容,本章我们并不是深入讲解C&C内存管理,而是介绍C&C内存管理的基础知识,为我们以后深入理解C&C内存管理做铺…

基于 U-Net 网络的遥感图像语义分割 完整代码+论文

一、研究目的U-Net 是一种由全卷积神经网络启发的对称结构网络,在医疗影像分割领域取得了很好的效果。 此次研究尝试使用 U-Net 网络在对多光谱遥感影像数据集上进行训练,尝试使用卷积神经网络自动分割出建筑,希望能够得到一种自动分割遥感影…

ElementUI分页的实现

官网地址&#xff1a;Element - The worlds most popular Vue UI framework 第一步&#xff1a;拷贝你喜欢的分页类型放在你的组件页面需要用到的分页位置 <el-paginationsize-change"handleSizeChange"current-change"handleCurrentChange":current-p…

1.JAVA-JDK安装

前言&#xff1a;工具下载地址阿里云盘&#xff1a;Java-Jdk&#xff1a;https://www.aliyundrive.com/s/JpV55xhVq2A提取码: j53y一、jdk下载&#xff1a;前往Oracle官网可免费下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/ 此处我下载的是jdk8&a…

【nas折腾篇】抉择吧,是入门还是放弃

2018年公司一位女同事问群晖的nas是否值得买。我一脸懵&#xff0c;以前给公司买云服务有采购nas盘&#xff0c;直接mount挂到服务器上当存储&#xff0c;但对于单独的nas服务器没有什么概念。一晃几年过去了&#xff0c;陆续刷到些nas服务的视频&#xff0c;周边朋友用nas的也…

nginx的介绍及源码安装

文章目录前言一、nginx介绍二、nginx应用场合三、nginx的源码安装过程1.下载源码包2.安装依赖性-安装nginx-创建软连接-启动服务-关闭服务3.创建nginx服务启动脚本4.本实验---纯代码过程前言 高可用&#xff1a;高可用(High availability,缩写为 HA),是指系统无中断地执行其功…

OSI七层模型与物理层与设备链路层

目录 协议 举例 OSI七层模型 理解七层模型 以下为OSI七层模型数据逐层封装和数据逐层解封的过程 TCP/IP参考模型 数据包的层层封装与层层拆包 各层的数据以及协议 封装所用的协议的数字表示形式 物理层 模拟信号 模拟信号特点 数字信号 数字信号特点 数据通信模…

【存储】etcd的存储是如何实现的(3)-blotdb

前两篇分别介绍了etcd的存储模块以及mvcc模块。在存储模块中&#xff0c;提到了etcd kv存储backend是基于boltdb实现的&#xff0c;其在boltdb的基础上封装了读写事务&#xff0c;通过内存缓存批量将事务刷盘&#xff0c;提升整体的写入性能。botldb是etcd的真正的底层存储。本…

CSS预处理器sass和less

文章目录CSS预处理器什么是CSS预处理器Sass和LESS背景介绍Sass背景介绍LESS的背景介绍Sass安装Sass下载Ruby安装文件安装Ruby安装Sass编译Sass命令行编译命令行编译配置选项四种编译排版演示nested 编译排版格式expanded 编译排版格式compact 编译排版格式compressed 编译排版格…