【LeetCode】141.环形链表、142. 环形链表 II(算法 + 图解)

Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
🌱🌱个人主页:奋斗的明志
🌱🌱所属专栏:数据结构

在这里插入图片描述

📚本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。

在这里插入图片描述

链表面试题

  • 一、环形链表
    • 1. 题目
    • 2. 解析
    • 3. 完整代码
  • 二、环形链表 II
    • 1. 题目
    • 2. 解析
    • 3. 完整代码
  • 三、总结

一、环形链表

141.环形链表


1. 题目


在这里插入图片描述
在这里插入图片描述


2. 解析


【思路】

快慢指针,即慢指针一次走一步,快指针一次走两步,两个指针从链表起始位置开始运行,如果链表 带环则一定会在环中相遇,否则快指针率先走到链表的末尾。比如:陪女朋友到操作跑步减肥。

【扩展问题】

  • 为什么快指针每次走两步,慢指针走一步可以?

假设链表带环,两个指针最后都会进入环,快指针先进环,慢指针后进环。当慢指针刚进环时,可能就和快指针相遇了,最差情况下两个指针之间的距离刚好就是环的长度。此时,两个指针每移动一次,之间的距离就缩小一步,不会出现每次刚好是套圈的情况,因此:在慢指针走到一圈之前,快指针肯定是可以追上慢指 针的,即相遇。

  • 快指针一次走3步,走4步, …n步行吗?

在这里插入图片描述

在这里插入图片描述


快慢指针初始化:

  • ListNode fast = head;:快指针从链表头部开始。
  • ListNode slow = head;:慢指针也从链表头部开始。

遍历过程:

  • while (fast != null && fast.next != null):使用快指针和慢指针遍历链表,条件是快指针不为 null 且快指针的下一个节点也不为 null。
  • fast = fast.next.next;:快指针每次向前移动两步。
  • slow = slow.next;:慢指针每次向前移动一步。

检测环:

  • if (fast == slow):在每次迭代中,检查快慢指针是否相遇。如果相遇,说明链表中存在环,返回 true。

结束条件:

  • 如果遍历完链表(即 fast 或者 fast.next 为 null ),仍未找到相遇点,则链表中不存在环,返回 false。

总结:

  • 该算法利用快慢指针的技巧来判断单链表中是否存在环,时间复杂度为 O(n)空间复杂度为 O(1),非常高效。

3. 完整代码


/*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/
public class Solution {public boolean hasCycle(ListNode head) {// 定义两个指针ListNode fast = head;ListNode slow = head;// 使用快慢指针进行遍历while (fast != null && fast.next != null) {fast = fast.next.next; // 快指针每次走两步slow = slow.next; // 慢指针每次走一步if (fast == slow) { // 如果快慢指针相遇,说明有环return true;}}return false; // 遍历结束,没有环}
}

二、环形链表 II

142. 环形链表 II


1. 题目


在这里插入图片描述
在这里插入图片描述


2. 解析

重画链表如下所示,线上有若干个节点。记蓝色慢指针为 slow,红色快指针为 fast。初始时 slow 和 fast 均在头节点处。
在这里插入图片描述
使 slow 和 fast 同时前进,fast 的速度是 slow 的两倍。当 slow 抵达环的入口处时,fast 一定在环上,如下所示。
在这里插入图片描述
其中:

head 和 A 的距离为 z
弧 AB (沿箭头方向) 的长度为 x
同理,弧 BA 的长度为 y

可得:

slow 走过的步数为 z
设 fast 已经走过了 k 个环,k≥0,对应的步数为 z+k(x+y)+x
以上两个步数中,后者为前者的两倍,即 2z=z+k(x+y)+x 化简可得 z=x+k(x+y),替换如下所示。
在这里插入图片描述
此时因为 fast 比 slow 快 1 个单位的速度,且y 为整数,所以再经过 y 个单位的时间即可追上 slow。

即 slow 再走 y 步,fast 再走 2y 步。设相遇在 C 点,位置如下所示,可得弧 AC 长度为 y。

在这里插入图片描述

因为此前x+y 为环长,所以弧 CA 的长度为 x。 此时我们另用一橙色指针 ptr (pointer) 指向 head,如下所示。并使 ptr 和 slow 保持 1 个单位的速度前进,在经过 z=x+k(x+y) 步后,可在 A 处相遇。
在这里插入图片描述
再考虑链表无环的情况,fast 在追到 slow 之前就会指向空节点,退出循环即可。


在这里插入图片描述


由上一题可以求出相遇点,这里的相遇点是假设的
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
走不确定圈数的时候:


在这里插入图片描述
在这里插入图片描述
初始化指针:

  • ListNode fast = head;:快指针从链表头部开始。
  • ListNode slow = head;:慢指针也从链表头部开始。

检测环:

  • 使用两个指针 fastslow 同时遍历链表,其中 fast 每次移动两步,而 slow 每次移动一步``。
  • 如果链表中存在环,快指针 fast 最终会追上慢指针 slow

找出环的起始点:

  • 一旦快慢指针相遇,就说明链表中有环。
  • 将 slow 指针重新指向链表头部。
  • 接着,快指针 fast 和慢指针 slow 同时每次移动一步,直到它们再次相遇。这次相遇点即为环的起始点。

返回结果:

  • 如果找到了环的起始点,就返回这个节点;否则返回 null,表示链表中无环。

3. 完整代码


/*** Definition for singly-linked list.* class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head;ListNode slow = head;while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;if(fast == slow){slow = head;while(fast != slow){fast = fast.next;slow = slow.next;}return fast;}}return null;}
}

三、总结

  • 链表(Linked List)是最简单的线性的、动态数据结构。理解它是理解树结构、图结构的基础。

  • 区别于数组,链表中的元素不是存储在内存中连续的一片区域,链表中的数据存储在每一个称之为「结点」复合区域里,在每一个结点除了存储数据以外,还保存了到下一个节点的指针(Pointer)。

在这里插入图片描述

  • 由于不必按顺序存储,链表在插入数据的时候可以达到O(1)的复杂度,但是查找一个节点或者访问特定编号的节点则需要 O(n) 的时间。

  • 使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

  • 在计算机科学中,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向上一个/或下一个节点的位置的链接(links)。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的访问往往要在不同的排列顺序中转换。而链表是一种自我指示数据类型,因为它包含指向另一个相同类型的数据的指针(链接)。

  • 链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。

  • 链表通常可以衍生出循环链表,静态链表,双链表等。对于链表使用,灵活使用虚拟头结点可以简化问题。

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

AI学习记录 - 本地知识库实现的相关知识

在公司内部实现了个知识库,但这里只介绍在实现知识库的过程中用到的知识。 1、分词器 先分词,中文可以使用jieba分词 2、构造数据集 将词汇向量化是自然语言处理中的重要任务,它可以将文本数据转化为计算机能够理解和处理的向量形式。以…

在react中如何计算本地存储体积

1.定义useLocalStorageSize钩子函数 // 计算localStorage大小 function useLocalStorageSize() {const [size, setSize] useState(0);useEffect(() > {const calculateSize () > {let totalSize 0;for (let key in localStorage) {//过滤掉继承自原型链的属性if (loc…

抄作业-跟着《React通关秘籍》捣鼓React-playground-上集

文章目录 前言1. 搭建react 开发环境2、react hooks 知识3. 目标:跟着小册实现 react-playground3.1 整体布局初始化项目使用Alloment 来实现左右分屏的拖拉功能 3.2 代码编辑器Monaco Editor 3.3 实现了多文件的切换用 useContext 来共享数据。优化 tab的样式&…

扫雷游戏小程序

目录 一.文件 1.头文件 2.源文件 二.游戏界面和执行(test.c) 三.函数实现(void game部分,源文件game.c) 1.定义雷二维数组和展示二维数组 2.初始化地雷数组 3.初始化显示的数组 4.显示当前的情况 5.随机放置地雷 6.排雷 ps:深度优先遍历数组 四.结束 一.文件 1.头…

《Single-Stage Extensive Semantic Fusion for multi-modal sarcasm detection》

系列论文研读目录 文章目录 系列论文研读目录文章题目含义ABSTRACTKeywords1. Introduction2. Related work3. Method3.1. Multi-modal projection 多模态投影3.2. Extensive Semantic Fusion Multiway Transformer 可拓语义融合多路Transformer3.3. Multi-objective optimizat…

LeetCode 热题 HOT 100 (011/100)【宇宙最简单版】

【图论】No. 0200 岛屿数量 【中等】👉力扣对应题目指路 希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦 欢迎关注、订阅专栏 【力扣详解】谢谢你的支持&#xf…

DjangoRF-10-过滤-django-filter

1、安装pip install django-filter https://pypi.org/ 搜索django-filter基础用法 2、进行配置 3、进行内容调试。 4、如果碰到没有关联的字段。interfaces和projects没有直接关联字段,但是interface和module有关联,而且module和projects关联&#x…

linux下使用yum安装mysql

本文使用常规方式手动安装mysql 第一步 下载mysql的repo源 wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm第二步 安装mysql-community-release-el7-5.noarch.rpm包 rpm -ivh mysql-community-release-el7-5.noarch.rpm第三步 安装mysql-server yum -y…

Esp_server 安卓嵌入壳子,原创! 2024/7/28 20:58

用到的软件: uni-app 思路: 让用户感觉是,一个完整的程序.实际上只是一个类浏览器壳子.轻便小巧. 由于是第一次用uni-app开发类软件,所以前前后后耗费7小时! 隔行如隔山,不是白讲的. 软件界面: 软件功能: 简化输入: 输入ip地址,例:http:// www.baidu.com 完整网址 前面…

Javaer 5分钟入门 Golang

文章目录 前言一个 go 文件长啥样?Go 语言的变量变量类型变量声明 Go 语言的函数&方法Go 语言没有的概念访问修饰符面向对象模型异常处理机制 Go 语言高效简洁的并发编程总结 前言 这两年主流的编程语言 Golang,想必大家或多或少都接触过。云原生领…

使用 Docker Compose 部署 RabbitMQ 的一些经验与踩坑记录

前言 RabbitMQ 是一个功能强大的开源消息队列系统,它实现了高效的消息通信和异步处理。 本文主要介绍其基于 Docker-Compose 的部署安装和一些使用的经验。 特点 成熟,稳定消息持久化灵活的消息路由高性能,高可用性,可扩展性高支…

【PYTHON】多进程运行示例含共享数据

运行结果 Python多进程调用示例 import multiprocessing import time import os import sys# 注册多个函数用于不同进程分别调用 def testcase0():time.sleep(1)return "case0_"get_time()def testcase1(timestamp):return "case1_"timestampdef testcase…

Python | TypeError: ‘float’ object is not subscriptable

Python | TypeError: ‘float’ object is not subscriptable 在Python编程中,遇到“TypeError: ‘float’ object is not subscriptable”这一错误通常意味着你尝试对浮点数(float)使用了下标访问(如数组或列表那样的访问方式&a…

Mindspore框架循环神经网络RNN模型实现情感分类|(四)损失函数与优化器

Mindspore框架循环神经网络RNN模型实现情感分类 Mindspore框架循环神经网络RNN模型实现情感分类|(一)IMDB影评数据集准备 Mindspore框架循环神经网络RNN模型实现情感分类|(二)预训练词向量 Mindspore框架循环神经网络RNN模型实现…

探索 Blockly:自定义积木实例

3.实例 3.1.基础块 无输入 , 无输出 3.1.1.json var textOneJson {"type": "sql_test_text_one","message0": " one ","colour": 30,"tooltip": 无输入 , 无输出 };javascriptGenerator.forBlock[sql_test_te…

数据结构:二叉树(堆)的顺序存储

文章目录 1. 树1.1 树的概念和结构1.2 树的相关术语 2. 二叉树2.1 二叉树的概念和结构2.2 二叉树的特点2.3 特殊的二叉树2.3.1 满二叉树2.3.2 完全二叉树 2.4 二叉树的性质 3. 实现顺序结构二叉树3.1 堆的概念和结构3.2 初始化3.3 销毁3.4 插入数据3.5 向上调整算法3.6 删除数据…

【二叉树】—— 算法题

一、单值二叉树 题目要求:判断二叉树是不是单值二叉树(就是所以节点的值都相等)。 思路: 利用二叉树的递归思想,判断每一个节点值与其左右子节点的值是否相等,如果遇到空节点,就返回true&#…

醒醒,别睡了...讲《数据分析pandas库》了—/—<7>

一、 1、处理缺失值 1.1 认识缺失值 系统默认的缺失值 None 和 np. nan datapd.Series([3,4,np.nan,1,5,None]) dfpd.DataFrame([[1,2,None],[4,np.nan,6],[5,6,7]]) 1.2 缺失值查看 直接调用info() 方法就会返回每一列的缺失情况。 dfpd.DataFrame([[1,2,np.nan],[4,np.n…

在Linux中,MySQL备份与恢复

随着自动化办公与电子商务的不断发展,企业对于信息系统的依赖性越来越高,而数据库在信息系统中担任着非常重要的角色。尤其一些对数据可靠性要求非常高的行业,如银行、证券、电信等,如果发生意外宕机或数据丢失,其损失是非常严重的…

[ACTF2020 新生赛]Upload1

打开靶机,发现什么都没有 查看源码发现有个表单,不过高度为0,所以被隐藏了,我们直接找打css文件,清空(也可以设置原始高度) 然后提交木马脚本,直接提交PHP不通过 修改为phtml&#x…