LeetCode_(兜兜转转还是你)浪漫的环形链表问题

✨✨所属专栏:LeetCode刷题专栏✨✨

✨✨作者主页:嶔某✨✨

 第一题:

 这道题的代码很简单,但是后续的一些问题在思考的过程是很复杂的。下面我们就一起来分析一下吧!

 链表带环的意思就是说链表的某个节点的next指针指向了前面的某个节点(如图),当然、在极端情况下,也可能指向自己。我们在做题的时候可以将上图抽象成下图:

 快慢指针:我们定义两个指针fast、slow都指向头节点,每一次循环让fast走两步,slow走一步。

(1)链表中带环:那么fast先进环,slow后进环。这时就变成了追及相遇问题了,如果最后fast指针等于slow指针,那么说明链表带环,返回true。

(2)链表中不带环:如果fast走向空指针了,说明链表不带环,返回false。所以我们以fast和fast的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;
}

 那么接下来,我们思考这样一个问题:先前我们是让fast一次走两步,slow一次走一步。那如果fast一次走三步、四步、五步呢?

这里我们讨论fast一次走三步的情况:

 假设当slow也进环时,fast于slow指针之间的节点个数为 N 这里就有两种情况:

(1)N为偶数:那么距离变化:N -> (N-2) -> (N-4) ->......-> 4 -> 2 -> 最后fast == slow。

(2)N为奇数:距离变化:N -> (N-2) -> (N-4) ->......->3 -> 1 -> (-1)最后还是错过了……

我们不仅追不上,在一些步数差上,我们还会在接触后渐行渐远……

 我们爱的奋不顾身,殊不知,这正好让我们渐行渐远……

那么当N为奇数时,错过后就真的没有挽回的余地了吗?我们接着分析:

当fast和slow之间的距离为 -1 时,实际上它们之间的距离为: (C - 1)

(1)我们之间又开始了下一段追及相遇,同上,当 (C - 1)为偶数时,刚好追上。

(2)当 (C - 1)为奇数时就永远追不上了。因为(C - 1)为奇数,下一次我们也必然会错过,一旦错过就是万劫不复……

所以这里我们得出结论当N为奇数且C为偶数时:他们两个永远也追不上彼此。

但……真的是这样吗?或者说你真的甘心就是如此了吗?

C和N有没有可能都为奇数或者都为偶数呢?

我们不妨继续分析

假设当slow进环的时候,fast已经在环里面转了x圈了,这时fast指针走的总路程为:

L + x*C + N

而slow只走了 L 这么长的距离,由于slow每次走一步,fast每次走三步,所以fast走的路程为slow的三倍,我们得到以下关系:

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

 整理一下:

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

等号左边为偶数,如果N为奇数,C为偶数,一个偶数减一个奇数,不可能为偶数。所以不可能同时满足N为奇数、C为偶数或者C为奇数、N为偶数。

只能是它们两个同时为奇数或者同时为偶数。

所以我们一定会再次相遇……

 就算我们错过了,亲爱的,我们还会遇见的……

 第二题:

 这道题的代码也很简单,但是思考的过程是很复杂的,我们一起来分析一下:

这里我们要确定入环的第一个节点这里有一个O(n^2)的算法,就是将链表的每一个节点都判断一下然后让一个指针一直往后走,如果最终这个指针和此节点相等了,那么此节点就是要寻找的第一个节点。

但是此算法太过复杂,有没有更好一点的算法呢?

这里我们给出一种代码简单的算法:

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(slow == fast)
        {
            struct ListNode* meet = fast;
            while (meet != head)
            {
                head = head->next;
                meet = meet->next;
            }
           	return meet;
        }
	}
    return NULL;
}

我们让一个节点在快慢指针的地方开始,另一个指针从头节点开始走,它们相遇的地方就是入环的第一个节点。

为什么呢?

 老样子,我们来分析一下:

当fast和slow相遇时:

fast走过的路程为:L + x*(C) + N

slow走过的路程为:L + N

而fast走的步数是slow的二倍,我们就有:

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

整理一下:

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

这个试子就很好的说明了为什么head和meet会在入环节点相遇。

当x = 1时:meet正好走完C - N的路程后就与head再入环节点相遇

当x > 1时:meet走了(x - 1)圈后再走(C - N)就会和head在入环节点相遇

  本期博客到这里就结束了,如果有什么错误,欢迎指出,如果对你有帮助,请点个赞,谢谢!

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

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

相关文章

定位系统源码,工厂人员定位系统源码,UWB高精度定位系统源码

一套java定位系统源码,工厂人员定位系统源码,UWB高精度定位系统源码,前后端分离架构,源码有演示。 工厂人员定位系统,高精度的位置数据作为智能工厂数据流的重要组成部分,可实现对工厂内的人,车…

环状串的字典序

【题目描述】 长度为n的环状串有n种表示法,分别为从某个位置开始顺时针得到。例如,图3-4的环状串有10种表示: CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等。在这些表示法中,字典序最小的称为"最小表示"…

利用GaussDB的可观测性能力构建故障模型

D-SMART高斯专版已经开发了几个月了,目前主要技术问题都已经解决,也能够初步看到大概的面貌了。有朋友问我,GaussDB不已经有了TPOPS了,为什么你们还要开发D-SMART高斯专版呢? 实际上TPOPS和D-SMART虽然都可以用于Gaus…

区块链技术下的DApp与电商:融合创新,开启商业新纪元

区块链技术的蓬勃发展正引领着一种新型应用程序的崛起——去中心化应用程序(DApp)。DApp并非传统的中心化应用,它构建于去中心化网络之上,融合了智能合约与前端用户界面,为用户提供了全新的交互体验。智能合约&#xf…

01.Kafka简介与基本概念介绍

1 Kafka 简介 Kafka 是最初由 Linkedin公司开发,是一个分布式、支持分区(partition)的、多副本(replica)的,基于 Zookeeper 协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于 hadoop 的…

算法工程师——算法岗的分类及要求汇总

算法岗工程师 根据 Talent Seer 人才报告显示,全球 AI 从业者总人数约有 30 万,还是供不应求,其中 AI 技术专家(具有相关领域博士学位及 3 年以上工作经验的)约有 3.65 万。 简介 对于计算机专业的毕业生而言,算法岗基本上就是 「高薪」 的代名词。 在当今 IT 行业,算…

如何将本地项目上传到Github(SSH方式)

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

训练营第三十七天动态规划(基础题part3)

训练营第三十七天动态规划(基础题part3) 343. 整数拆分 力扣题目链接 题目 给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k > 2 ),并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 …

一篇文章 学会Qt 样式表(qss)

QML 中风格和主题的设计可以通过配置文件选择现有几种中的一种,或者直接在控件定义时,指定其属性,如背景颜色或者字体大小。在QWidget框架中,则通过了一种叫做qss样式表的东西来进行描述,跟CSS逻辑上类似。 这个qss抽…

【Redis 开发】多级缓存,本地进程缓存Caffeine

多级缓存 多级缓存本地进程缓存CaffeineCaffeine三种缓存驱逐策略 多级缓存 Redis处理并发的能力是非常强大的,但是tomcat的支持并发的能力跟不上Redis的性能,导致整体性能的下降 Redis缓存失效时,会对数据库产生冲击,之间再无屏…

自动驾驶横向控制算法

本文内容来源是B站——忠厚老实的老王,侵删。 三个坐标系和一些有关的物理量 使用 frenet坐标系可以实现将车辆纵向控制和横向控制解耦,将其分开控制。使用右手系来进行学习。 一些有关物理量的基本概念: 运动学方程 建立微分方程 主要是弄…

软件测试之学习及复习面试路线汇总

对于很多想通过自学或面试复习软件测试的同学,痛点并不是学习动力,而是找不到清晰的学习思路。 熬夜3天,吐血整理了这份《软件测试学习路线》,全文接近6000字,请大家耐心看完! 软件测试职业成长图 第一阶…

数字信号的产生与检测——DSP学习笔记六

本专栏的博客的图片大部分来源于老师的PPT,本博客只是博主对于上课内容的知识结构的分析和梳理。 几种数字信号的产生 正弦波信号 多项式逼近(除了泰勒展开,还有一种方法是切比雪夫逼近法,感兴趣可以自己去了解一下) 查找表 核心思…

HDFS分布式文件存储系统

1-1 HDFS的存储机制 按块(block)存储 hdfs在对文件数据进行存储时,默认是按照128M(包含)大小进行文件数据拆分,将不同拆分的块数据存储在不同datanode服务器上 拆分后的块数据会被分别存储在不同的服务器上 副本机制 为了保证hdfs…

python环境安装jupyter

安装完毕之后下一步可以参考:配置jupyter的启动路径-CSDN博客 1 前提条件:python环境 系统:win10 python:本地已经有python,可以查看本地的python版本: C:\Users\PC>python --version Python 3.8.10 …

腾讯企点点击网址系统默认Google浏览器无法打开

最近更新了Chrome,企点里的信息无法自动完成链接跳转。 但是无法看卡在哪里。用了同事推荐的方法。把默认应用改成其他浏览器先测试。 其他浏览器没有问题,那就是Google浏览器有问题。尝试直接到软件目录双击打开。会弹出用户账户控制界面,询…

解决Blender导出FBX文件到Unity坐标轴错误的问题

发现Blender的模型导入到Unity里面有问题,简单研究了下发现是坐标系不同,Unity使用的是左手坐标系,Blender使用的是右手坐标系 。 下面直接将如何解决 首先忽略Blender的右手坐标系以及Z轴朝上的事,依照unity坐标系情况修改模型物体的旋转,以Blender猴…

Hystrix断路器

Hystrix断路器 概述分布式系统面临的问题什么是Hystrix 服务熔断什么是服务熔断添加方法 服务降级什么是服务降级实现方法 服务监控hystrixDashboard 概述 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候不可避免地…

Python网络数据抓取(3):Beautiful Soup

Beautiful Soup 这个库通常被称为Beautiful Soup 4(BS4)。它主要用来从HTML或XML文件中抓取数据。此外,它也用于查询和修改HTML或XML文档中的数据。 现在,让我们来了解如何使用Beautiful Soup 4。我们将采用上一节中使用的HTML数据…

【优质书籍推荐】ChatGLM3大模型本地化部署、应用开发与微调

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…