《程序员面试金典(第6版)》面试题 02.08. 环路检测(哈希法,双指针,检测链表是否有环)

题目描述

给定一个链表,如果它是有环链表,实现一个算法返回环路的开头节点。若环不存在,请返回 null。
题目传送门:面试题 02.08. 环路检测

  • 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

示例 1:

在这里插入图片描述

 输入:head = [3,2,0,-4], pos = 1
 输出:tail connects to node index 1
 解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

在这里插入图片描述

输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

在这里插入图片描述

输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。

进阶:

  • 你是否可以不用额外空间解决此题?

解题思路与代码

  • 这道题算是比较简单的一道题。检测链表是否存在环的最简单的一种方法是哈希法,其次就是快慢指针法。那么前者的空间复杂度可能会高些,但是代码结构简单易懂。

  • 后者虽然说比前者稍微难点,但也没有难太多,多了一点点的思考量而已。

总的来说,这道题是一道好题,考验了你一点点的数学思维,与链表的实际操作

方案一:哈希法

这道题如果是单单的判断链表是否成环,那这道题就是一道简单题,如果还要让你去返回成环的开头节点,那这道题的难度就要上升了。

对于这道题,如果我们用了哈希法,那就是降维打击,因为我们利用unordered_set就可以直接帮你返回相同节点。
具体的代码如下:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        unordered_set<ListNode*> set;
        while(head){
            if(set.count(head)) return head;
            set.insert(head);
            head = head->next;
        }
        return nullptr;
    }
};

在这里插入图片描述

复杂度分析:

  • 时间复杂度:O(n),其中n是链表节点的个数
  • 空间复杂度:O(n),我们需要将链表的每一个节点放入集合中,所以是O(n)

方案二: 快慢指针法

  • 先解释一下这里的快慢指针法是什么意思。在这里,我们先设置两个指针,p1,p2。 p1一次走一格,p2一次走两个。因为他们走的步数不一样,所以,如果链表中有环存在了话,那么p1,p2一定不会相等。反之,如果有环,那p1,p2一定会相等。

那这道题的难点在成环节点,在距离头节点多少位置呢?首先,我们要画图分析。
在这里插入图片描述

  • 我们设从头节点,到成环节点的距离为a,成环节点到p2追到p1的距离为b,被追到的p1节点距离再次回到成环节点的距离为c。

  • p2指针一次走两格,p1指针一次走一格,p2追上p1的时候,p2走过的距离是p1的两倍。

  • p1被追到时p2走了a + n(b + c) + b,p1走了a + b所以不难得出这个等式:a + n(b + c) + b = 2(a + b)

  • 将这个等式变化一下便是 **a = c + (n-1)(b+c)**么。

看着这个图,我们来翻译一个这个数学等式的意思。

  • 假设从头节点走了a步,到达了成环节点。便等于我在相遇节点走了 c 步 + n圈。
  • 我们在p1节点与p2节点相遇的时候,再去设置一个p3节点让它等于头节点。这个时候,p3也一次走一步。
  • 你看图,当p3在头节点走了a步的时候,是不是正好与p1在b的时候走了c步 + n圈呢?

具体代码如下:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* p1 = head;
        ListNode* p2 = head;
        while(p2){
            p1 = p1->next;
            if(p2->next)
                p2 = p2->next->next;
            else return nullptr;
            if(p1 == p2) {
                ListNode* p3 = head;
                while(p3!=p1){
                    p1 = p1->next;
                    p3 = p3->next;
                }
                return p3;
            }
        }
        return nullptr;
    }
};

在这里插入图片描述

复杂度分析:

  • 时间复杂度:O(N),N为节点的长度。因为你在实际推演的过程中会发现,p1指针走过的最长的路程也不会超过链表中节点的个数,而是等于节点的个数,所以时间复杂度是O(N)
  • 空间复杂度:O(1),我们设置了几个变量而已,没有使用额外的数据结构,所以是O(1)。

总结

这道题目是一个经典的链表问题,经常出现在计算机科学和软件工程的面试和教程中。

这道题目的主要意义和重要性可以从以下几个方面来看:

  • 数据结构理解与应用:这道题目需要你理解和操作链表这种基础数据结构。理解数据结构的特性和操作方法是编程和算法学习的基础。

  • 双指针技巧:这道题目需要使用到双指针(快慢指针)的技巧。这是一个常用的算法设计策略,可以帮助解决一些看似复杂的问题。

  • 算法分析:通过这道题目,你需要理解和分析算法的时间复杂度和空间复杂度。这道题的解决方案有一个很好的性质:它只需要常量的额外空间,且时间复杂度为线性。

  • 问题解决和调试能力:这道题目也可以帮助你提升问题解决和调试的能力。理解为什么这个解决方案能够工作,对于提升你的算法设计和问题解决能力是非常有帮助的。

所以,这道题目的意义不仅仅是解决一个具体的问题,更重要的是通过这个问题来学习和提升你的数据结构知识,算法设计和问题解决能力。

最后的最后,如果你觉得我的这篇文章写的不错的话,请给我一个赞与收藏,关注我,我会继续给大家带来更多更优质的干货内容

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【笔记整理】常见聚类算法

【笔记整理】常见聚类算法 文章目录 【笔记整理】常见聚类算法一、均值偏移 - Mean-shift&#xff08;★★★★&#xff09;1、概述 & 图解&#xff08;“偏心”&#xff09;2、公式 & 步骤1&#xff09;基本公式&#xff08;“偏移量更新圆心”&#xff09;2&#xff…

4:File类与IO流

文章目录 File类1&#xff1a;引入&#xff1a;2&#xff1a;对文件进行操作3&#xff1a;对目录/文件夹进行操作 IO流1&#xff1a;引入&#xff1a;2&#xff1a;字符输入 / 出流FileReader 与 FileWriter3&#xff1a;用try - catch - finally 处理异常4&#xff1a;几个常见…

【Android-JetpackCompose】13、实战在线课程 App

文章目录 一、BottomNavigation 底部导航1.1 底部导航栏的布局、点击1.2 设置 bottomBar 的颜色1.3 设置顶部 actionBar 的颜色 二、主页 StudyScreen2.1 顶部状态栏2.2 一、BottomNavigation 底部导航 1.1 底部导航栏的布局、点击 首先&#xff0c;构造 NavigationItem 的 d…

c++—断言、异常

一、 断言&#xff0c;主要用于在函数入口处进行参数检查&#xff0c;是否符合参数设置要求&#xff1b; &#xff08;1&#xff09;true&#xff1a;继续执行&#xff1b;false&#xff1a;终止运行&#xff1b; &#xff08;2&#xff09;特点&#xff1a;在程序运行时才能起…

【20】SCI易中期刊推荐——计算机信息系统工程电子与电气(中科院3区)

💖💖>>>加勒比海带,QQ2479200884<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉…

zookeeper学习笔记

zookeeper Zookeeper 入门概述Zookeeper工作机制特点数据结构应用场景统一命名服务统一配置管理统一集群管理服务器动态上下线软负载均衡 zookeeper安装本地模式安装配置参数解读 Zookeeper 集群操作集群操作集群安装 选举机制节点类型客户端命令行操作命令语法znode 节点数据信…

mysql 是否包含 返回索引 截取字符串

是否包含返回索引 原文链接&#xff1a;https://www.cnblogs.com/shoshana-kong/p/16474175.html 方法1&#xff1a;使用通配符%。 通配符也就是模糊匹配&#xff0c;可以分为前导模糊查询、后导模糊查询和全导匹配查询&#xff0c;适用于查询某个字符串中是否包含另一个模糊…

Redis的全局命令及相关误区

Redis中所说的数据结构是针对key-value中的value而言的。主要的结构包括String、哈希表、列表、集合等等在redis中存在16个库&#xff0c;涉及到后期的集群搭建只能使用0号库最为方便 查看所有键&#xff08;支持通配符&#xff09; keys * keys S*返回当前数据库中的键总数 …

智能出行更安全,亚马逊云科技携手木卫四助汽车客户安全合规出海

木卫四&#xff08;北京&#xff09;科技有限公司在汽车网络安全领域拥有独特专业知识&#xff0c;其融合人工智能算法的安全检测引擎可以不依赖车辆中安装的代理软件&#xff0c;只需几周即可快速部署实施&#xff0c;是汽车网络安全领域的技术领先者。 在亚马逊云科技初创团…

ChatGPT国内镜像站

免费国内镜像推荐&#xff08;超稳定&#xff09; 下面为大家收集了目前国内最稳定流畅的ChatGPT镜像网站 目录 机器人 博弈ai 泰cool辣 道合顺 二狗问答 核桃 WOChat GPT中文站 TomChat 利用ChatGPTMindShow三分钟生成PPT ChatGPT国内镜像是啥 ChatGPT 镜像是指…

大语言模型技术原理

在今天这个时代&#xff0c;人们的工作和生活已经离不开数据访问&#xff0c;而几乎所有平台背后的数据存储和查询都离不开数据库。SQL作为一种数据库的查询和处理语言历史悠久&#xff0c;最早由IBM于上世纪70年代初研究关系数据模型时提出&#xff0c;后续发展为一种广泛使用…

帕累托改进和帕累托最优、卡尔多-希克斯改进

根据目标个数&#xff0c;分为单目标规划&#xff0c;以及多目标规划。多目标的规划是去找折中的解集合&#xff0c;既pareto最优解集合。对优化目标超过3个以上的&#xff0c;称之为超多目标优化问题。 帕累托改进描述的就是在没有人变得不好的前提下让有些人更好的过程。帕累…

C#简单数据结构类和常用泛型结构类

文章目录 1.简单数据结构类&#xff08;1&#xff09;动态数组Arraylist&#xff08;2&#xff09;栈Stack&#xff08;3&#xff09;队列Queue&#xff08;4&#xff09;哈希表Hashtable 2.泛型3.常用泛型数据结构类&#xff08;1&#xff09;列表List&#xff08;2&#xff0…

Linux之基础IO

文章目录 前言一、再谈文件二、再谈文件操作二、如何理解文件1.文件操作的本质2.管理被打开的文件 三、进程和被打开的文件如何关联四、文件描述符fd1.引入2.理解3.分配规则 五、重定向1.引入重定向2.接口3.追加重定向4.输入重定向 总结 前言 本文介绍了系统IO、fd、重定向等内…

【Linux】在Ubuntu中卸载、下载mysql以及如何检查mysql是否卸载成功

介绍 这里是小编成长之路的历程&#xff0c;也是小编的学习之路。希望和各位大佬们一起成长&#xff01; 以下为小编最喜欢的两句话&#xff1a; 要有最朴素的生活和最遥远的梦想&#xff0c;即使明天天寒地冻&#xff0c;山高水远&#xff0c;路远马亡。 一个人为什么要努力&a…

micropython固件编译——把自己的py库添加进固件

目录 0. 前言1. 编写自己库的代码2. 移植库3. 验证 0. 前言 本节编译自己写的py库&#xff0c;增强移植性&#xff0c;往后烧录自己的固件即可轻易移植代码 没装好环境或者没有基础可以先看看这个&#xff1a; Ubuntu下ESP-IDF的环境搭建 Ubuntu下编译esp32micropython固件编…

windows下上架iOS应用到appstore

windows下上架iOS应用到appstore 背景步骤申请苹果开发者账号创建唯一标示符App IDs申请发布证书申请发布描述文件创建App并填写信息选择证书编译打包上传IPA到App Store提交审核 尾巴 背景 现在由于跨平台技术的兴起&#xff0c;不使用原生技术就能开发出Android和iOS应用。A…

一些关于c++的琐碎知识点

目录 bool强转 const构成重载:const修饰*p 移动构造 new int (10)所做的四件事 this指针---为什么函数里面需要this指针&#xff1f; .和->的区别 new创建对象 仿函数 new和malloc的区别 c系统自动给出的函数有 delete和delete[ ]区别何在 检查有没有析构函数 e…

BTC API:如何在比特币网络上创建应用程序?

比特币是一种去中心化的数字货币&#xff0c;可以通过比特币API与比特币网络进行交互。比特币API是一组允许开发人员与比特币网络进行交互的编程接口&#xff0c;可以帮助开发者构建各种比特币应用程序。 比特币API可以用于创建区块浏览器、钱包和比特币支付。其中利用比特币A…

Android-Activity生命周期

文章参考&#xff1a;添加链接描述 文章参考&#xff1a;添加链接描述 五大状态 StartingRunningStoppedPausedDestroyed 借用一张已经包浆的图 PS&#xff1a;Running和Paused是可视阶段&#xff0c;其余都是不可视 几大函数 onCreate&#xff1a;通过setContentLayout初始…