有关于链表带环的两道OJ题目

目录

1.判断链表是否带环

1.1快指针的速度为慢指针的2倍

1.2快指针的速度为慢指针的3倍

2.找出带环链表开始入环的第一个节点 

2.1将快慢指针相遇的节点与后面分开,构造交叉链表

2.2记录快慢指针相遇节点,与头结点一起向后走,相遇点为入环点


1.判断链表是否带环

141. 环形链表 - 力扣(LeetCode)

这道题目较为简单,我们知道,带环链表区别于不带环链表的一大特点就是它的最后一个节点指向链表中的某个节点,而不是NULL。

从这一点出发,我们可以探索出这道题的核心解法,定义一对快慢指针(slow和fast)在链表里面往下走,抓住带环链表往下走走不到头的特点,我们思考,大概率在慢指针入环后快指针会重新追上慢指针

好,那我们接下来就可以探讨一下这种方案的可行性啦~

1.1快指针的速度为慢指针的2倍

也就是慢指针走一步,快指针走两步这种情况。

依照我们正常的认知,这种情况非常可行~

那事实真是如此吗?哈哈,还真是如此!

如图所示,设slow进环时,fast与slow相距N个节点

进行下一步:

slow走一步,fast走两步,相距N-1个节点

slow走一步,fast走两步,相距N-2个节点

slow走一步,fast走两步,相距N-3个节点

.............

slow走一步,fast走两步,相距1个节点

slow走一步,fast走两步,相遇。

通过上述分析,快指针的速度为慢指针的2倍是完全可行的~

1.2快指针的速度为慢指针的3倍

也就是说慢指针走一步,快指针走三步。

经过第一种情况的讨论,你是否觉得这种情况不成立呢?

别着急,我们先来分析一波~

如图所示,设slow进环时,fast与slow相距N个节点

此时要分为两种情况讨论

1.当N为偶数时,进行下一步:

slow走一步,fast走三步,相距N-2个节点

slow走一步,fast走三步,相距N-4个节点

slow走一步,fast走三步,相距N-6个节点

...........

slow走一步,fast走三步,相距2个节点

slow走一步,fast走三步,相遇

2.当N为奇数时,进行下一步:

slow走一步,fast走三步,相距N-2个节点

slow走一步,fast走三步,相距N-4个节点

slow走一步,fast走三步,相距N-6个节点

...........

slow走一步,fast走三步,相距1个节点

slow走一步,fast走三步,相距-1个节点

看到相距-1个节点,此时出现的状况就是fast跳过了slow ,并没有遇上,所以后续是否能遇上还需要接着讨论。

那接下来我们就设环的总长度为C,此时两个指针相距C-1

此时还要分为两种情况讨论

1.当C为奇数,即C-1为偶数时,进行下一步: 

slow走一步,fast走三步,相距C-3个节点

slow走一步,fast走三步,相距C-5个节点

slow走一步,fast走三步,相距C-7个节点

...........

 slow走一步,fast走三步,相距2个节点

 slow走一步,fast走三步,相遇

2.当C为偶数,即C-1为奇数时,进行下一步:

slow走一步,fast走三步,相距C-3个节点

slow走一步,fast走三步,相距C-5个节点

slow走一步,fast走三步,相距C-7个节点

...........

slow走一步,fast走三步,相距1个节点

slow走一步,fast走三步,相距-1个节点

好,看到此时再次出现-1个节点,大部分人就可以笃定, “快指针的速度为慢指针的3倍”这种解法在N为奇数且C为偶数时,存在无法相遇的情况。

BUT!

请看以下分析!

在slow进环时,设前面没有环的部分长度为L,fast与slow相距N,环的长度为C,fast在环里面转了x圈。

根据fast走的长度是slow的三倍这个关系,列出以下等式 

3L=L+x*C+(C-N)

化简:2L=C*(x-1)-N

这里复习一下数学:奇数*奇数=奇数;奇数*偶数=偶数;偶数*偶数=偶数

可见,2L一定是个偶数,当C为偶数,N为奇数时,得到的结果一定为奇数,与2L为偶数相违背!

故:“在N为奇数且C为偶数时” 这种情况不存在!

即:快指针的速度为慢指针的3倍,可行!

之后往下的速度为4、5...倍关系就不一一展开讨论啦~ 

使用2倍方法的代码如下:

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

2.找出带环链表开始入环的第一个节点 

142. 环形链表 II - 力扣(LeetCode)

 这道题目是在上道题目基础上的延伸,想要找出环形链表入环的第一个节点可不能再用单纯只使用快慢指针了,因为快慢指针相遇点并不是环形链表入环的第一个节点。

那么该怎么写呢?

利用 “快指针的速度为慢指针的2倍” 这里提供两种思路:

2.1将快慢指针相遇的节点与后面分开,构造交叉链表

 这里首先说明一点:在slow入环之后,fast走的圈数不会超过两圈就能与slow相遇。所以相遇节点一定不是入环点!

这样的话,利用 “将快慢指针相遇的节点与后面分开,构造交叉链表” 这一思路,通过找到交叉链表的交叉点,就能找到入环点。

缺点就是需要的指针稍微有点多

2.2记录快慢指针相遇节点,与头结点一起向后走,相遇点为入环点

这种方法正常来说想不到,因为这是根据简单的数学推理得出

推理过程如下: 

(这部分与前面一样)在slow进环时,设前面没有环的部分长度为L,fast与slow相距N,环的长度为C,fast在环里面转了x圈。 

根据fast走的长度是slow的两倍这个关系,列出以下等式 

2L=L+x*C+(C-N)

化简:L=x*C+(C-N)

其中C-N代表相遇节点距离入环点剩下的节点。 

通过等式我们可以推理出:

当x=0时,L=C-N,刚好相遇节点与头结点距离入环点的长度相同。

当x!=0时,相遇节点与头结点距离入环点相差x个圈数,说明L相对较长,那么等头指针走完多余的x*C长度后,剩下的距离就是C-N了。

因此这种方法成立。

代码如下:

typedef struct ListNode ListNode;struct ListNode *detectCycle(struct ListNode *head) {ListNode*fast,*slow;fast=slow=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){ListNode*prev=head;while(prev!=slow){prev=prev->next;slow=slow->next;}return prev;}}return NULL;
}

---------------------------------------------------------------------------------------------------------------------------------

OK~  本次OJ题目分享就到这里

希望收获小伙伴们的支持!!!!

有问题欢迎在评论区评论哦~ 

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

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

相关文章

远程开启空调,享受即刻凉爽

随着夏季的热浪逐渐侵袭,我们都渴望回到家中那一刻,能感受到一丝丝的凉意。但是,有时候,即使我们提前开窗通风,房间里的温度依然像烤箱一样闷热难耐。那么,有没有一种方法,能让我们在外头酷暑难…

升级Nvidia CUDA 遇到 sub-process /usr/bin/dpkg returned an error code (1)

1.问题描述 在自己Ubuntu22.04的服务器环境上存在cuda版本为11.5,按照官网教程升级为12.1运行安装命令 sudo apt-get -y install cuda 报错:sub-process /usr/bin/dpkg returned an error code (1) 官网教程: https://developer.nvidia…

PCIE软件基础知识

什么是PCIE PCIe,全称 Peripheral Component Interconnect Express,是一种高速串行计算机扩展总线标准,用于连接计算机内部的硬件组件,如显卡、存储设备、网络适配器等。PCIe是一种点对点的双向通信标准,这意味着它在发…

微信小程序canvas 使用案例(一)

一、cavans 对象获取、上线文创建 1.wxml <!-- canvas.wxml --><canvas type"2d" id"myCanvas"></canvas> 2.js /*** 生命周期函数--监听页面加载*/onLoad(options) {const query wx.createSelectorQuery()query.select(#myCanvas).f…

分离式网络变压器的集成化设计替代传统网络变压器(网络隔离滤波器)尝试

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;今天分享的是应用了分离式网络变压器设计的的新型网络变压器&#xff08;网络隔离变压器&#xff09; 今天我们一起来看这款新型网络变压器&#xff0c;它就是应用分离式网络变压器集成到电路板上&#xff0c;加上外…

CAS乐观锁原理

1、什么是CAS&#xff1f; compare and swap也就是比较和交换&#xff0c;他是一条CPU的并发原语。 他在替换内存的某个位置的值时&#xff0c;首先查看内存中的值与预期值是否一致&#xff0c;如果一致&#xff0c;执行替换操作。 这个操作是一个原子性操作。 Java中基于Un…

昇思学习打卡-21-生成式/Diffusion扩散模型

文章目录 Diffusion扩散模型介绍模型推理结果 Diffusion扩散模型介绍 关于扩散模型&#xff08;Diffusion Models&#xff09;有很多种理解&#xff0c;除了本文介绍的离散时间视角外&#xff0c;还有连续时间视角、概率分布转换视角、马尔可夫链视角、能量函数视角、数据增强…

虚拟机迁移报错:虚拟机版本与主机“x.x.x.x”的版本不兼容

1.虚拟机在VCenter上从一个ESXi迁移到另一个ESXi上时报错&#xff1a;虚拟机版本与主机“x.x.x.x”的版本不兼容。 2.例如从10.0.128.13的ESXi上迁移到10.0.128.11的ESXi上。点击10.0.128.10上的任意一台虚拟机&#xff0c;查看虚拟机版本。 3.确认要迁移的虚拟机磁盘所在位…

操作系统---死锁相关

目录 一. 基础概念死锁的定义死锁与饥饿死锁产生原因死锁产生的必要条件资源分配圈&#xff1a;循环等待 VS 死锁 死锁处理策略 二. 死锁预防破坏互斥条件破坏不可剥夺条件破坏请求并保持条件破坏循环等待条件 三. 死锁的避免系统安全状态银行家算法 四. 死锁检测和解除死锁检测…

Mysql注意事项(一)

Mysql注意事项&#xff08;一&#xff09; 最近回顾了一下MySQL&#xff0c;发现了一些MySQL需要注意的事项&#xff0c;同时也作为学习笔记&#xff0c;记录下来。–2020年05月13日 1、通配符* 检索所有的列。 不建议使用 通常&#xff0c;除非你确定需要表中的每个列&am…

微软研发致胜策略 06:学无止境

这是一本老书&#xff0c;作者 Steve Maguire 在微软工作期间写了这本书&#xff0c;英文版于 1994 年发布。我们看到的标题是中译版名字&#xff0c;英文版的名字是《Debugging the Development Process》&#xff0c;这本书详细阐述了软件开发过程中的常见问题及其解决方案&a…

【运维】软件运维方案(2024word完整版)

1. 文档介绍 2. 人员与责任 3. 运维过程内容 4. 运维资源 5. 运维服务规划保障 6. 事件处置 7. 质量改进 8. 运维边界及内容 获取方式&#xff1a; 本文末个人名片直接获取。

2024年技校大数据实验室建设及大数据实训平台整体解决方案

随着信息技术的迅猛发展&#xff0c;大数据已成为推动产业升级和社会进步的重要力量。为适应市场需求&#xff0c;培养高素质的大数据技术人才&#xff0c;技校作为职业教育的重要阵地&#xff0c;亟需加强大数据实验室的建设与实训平台的打造。本方案旨在提出一套全面、可行的…

宿舍生活新升级:智能指纹锁的便捷体验(嘉立创EDA设计)

宿舍生活新升级&#xff1a;智能指纹锁的便捷体验 引言 宿舍生活总是充满挑战和乐趣&#xff0c;但有时也会因为一些小事情而变得复杂。比如&#xff0c;忘记带钥匙或者需要频繁地给室友开门。随着科技的发展&#xff0c;智能设备逐渐走进我们的生活&#xff0c;为日常带来便…

土耳其媒体发稿深化项目投放战略-脱颖而出

土耳其媒体发稿深化项目投放战略-脱颖而出 一、土耳其媒体的发展概况 土耳其拥有丰富的媒体资源&#xff0c;其中包括许多知名的新闻机构和周刊。随着互联网的普及和信息传播方式的变革&#xff0c;土耳其媒体不断调整发展策略&#xff0c;通过深化项目投放和多元化传播&…

代码随想录——一和零(Leetcode474)

题目链接 0-1背包 class Solution {public int findMaxForm(String[] strs, int m, int n) {// 本题m&#xff0c;n为背包两个维度// dp[i][j]:最多右i个0和j个1的strs的最大子集大小int[][] dp new int[m 1][n 1];// 遍历strs中字符串for(String str : strs){int num0 …

JESD204B学习与仿真

平台&#xff1a;vivado2018.3 芯片&#xff1a;xcku115-flva1517-2-i 场景&#xff1a;在高速ADC和DAC芯片中&#xff0c;有使用源同步的时钟和数据同步传输的方式&#xff0c;但是需要在逻辑内部对其进行校准。如果使用jesd204b接口传输数据&#xff0c;设计人员不需要了解…

从零训练一个多模态LLM:预训练+指令微调+对齐+融合多模态+链接外部系统

本文尝试梳理一个完整的多模态LLM的训练流程。包括模型结构选择、数据预处理、模型预训练、指令微调、对齐、融合多模态以及链接外部系统等环节。 01 准备阶段 1 模型结构 目前主要有三种模型架构&#xff0c;基于Transformer解码器&#xff0c;基于General Language Model&a…

【Python系列】Excel 文件到文本文件的转换

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

深入浅出理解 C 语言中的 qsort 函数

目录 引言 一、什么是qsort 二、函数原型 1.qsort函数 2.比较函数 三、qsort函数使用示例 1.使用qsort排序整形数据 2.使用qsort排序结构数据 总结 引言 在编程中&#xff0c;排序是一个常见且重要的操作。C 语言标准库提供了一系列排序函数&#xff0c;其中 qsort 函…