当前位置: 首页 > news >正文

[C/C++]数据结构 深入挖掘环形链表问题

前言

        在上一篇文章中讲述了如何判断链表是否带环,在观看本片文章时建议先了解一下这篇文章的内容[C/C++]数据结构 链表OJ题:环形链表。本篇文章我们将讲述关于环形链表的几种不同的情况如下,同时我们要解决另一个环形链表问题----找到入环点

  1. slow一次走一步fast一次走两步一定会相遇吗?
  2. slow一次走一步fast一次走三部一定会相遇吗?
  3. slow一次走n步fast一次走m步一定会相遇吗? (m>n>1)

情况分析:

1.slow一次走一步fast一次走两步一定会相遇吗?

        这个问题在上一篇文章中我们也讲过,若slow指针已经入环,每走一步fast与slow之间的距离就会减一,减为0时两指针相遇

2.slow一次走一步fast一次走三部一定会相遇吗?

        假设slow入环时,fast和slow之间距离为N

之后每走一步,fast和slow之间的距离就会减小2,这里就需要讨论N的取值了

  • 当N为偶数, 距离变化: N -> N-2 -> N-4.......->2 -> 0 ,两指针距离一次减小2,一定会相遇
  • 当N为奇数, 距离变化: N -> N-2 -> N-4.......->1 -> -1

        距离变为-1就说明fast在走三步的时候跳过了slow,又跑到了slow的前面,第一轮追逐没有相遇,此时又要开时第二轮追逐,假设环的周长为c,开始第二轮追逐时fast与slow之间的距离为c-1

此时有需要讨论c的取值

  • 当c为奇数,c-1为偶数,两指针一定会相遇
  • 当c为偶数,c-1为奇数,slow与fast就又不会相遇,同理这种情况无论第几次追逐两指针都不会相遇

总结:

  1. 如果N为偶数,两指针在第一轮追逐就会相遇
  2. 如果N为奇数,c为奇数,第一轮两指针会错过,但是在第二轮会相遇
  3. 如果N为奇数,为偶数,则两指针永远不会相遇

问题来了: 如果N为奇数,为偶数,则两指针永远不会相遇,但是这个条件成立吗?如何验证

slow入环时:

慢指针走的路程: L

快指针走的路程: n*c - N  (n代表走了n圈)

快指针所走路程为慢指针所走路程的三倍,可得:

3L = L+ n*c - N 即 2L = n*c - N

分析一下这个公式:

2L一定为偶数,n*c也一定为偶数,但是n*c-N一定为奇数,因为在条件N就为奇数,

所以我们推出来的公式是错的,也就是说如果N为奇数,为偶数,则两指针永远不会相遇这个条件不成立,即不会出永远追不上的情况,所以不论什么情况两指针都会在某一轮的追逐中相遇

3.slow一次走n步fast一次走m步一定会相遇吗? (m>n>1)

        这种情况和第二种情况分析过程类似,假设slow入环时,fast和slow之间距离为N,每走一步两者距离减(m-n),当N%(m-n)时,两指针便可相遇,由于这类问题给出实际值时才有意义,所以就不对其过多分析了


接下来我们解决最后一个问题:

如何找到链表的如环点?

题目描述:

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

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

不允许修改 链表。

分析:

这个题还是采用快慢指针的方法,slow一次走一步,fast一次走两步

由于fast速度是slow的二倍,所以相遇时,fast所走路程为slow的两倍,即

2*(L+x) = L+n*c+x

化简为: L = n*c - x

由这个公式就可以推出:

一个指针从头开始走,一个指针从相遇点开始走,他们会在入环点相遇

有了这个理论,这个题就可以迎刃而解了,我们先找出相遇点(如何找相遇点在前言所提文章中讲过),在让两指针,一个从头开始走,一个从相遇点开始走,判断哪个点符合这个公式

代码:


struct ListNode *detectCycle(struct ListNode *head) {struct ListNode *slow=head;struct ListNode *fast=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast)//找相遇点{struct ListNode* meet=slow;//相遇点while(meet!=head){head=head->next;meet=meet->next;}return meet;}}return NULL;
}

相关文章:

  • 线上 kafka rebalance 解决
  • 如何使用PHP替换回车为br
  • Spring 缓存注解
  • 2023-11-10 数据库-Presto-记录
  • Css问题:推荐几个超好看渐变色!项目中可用
  • 软件版本控制系统VCS工具——cvs vss svn git
  • 思科C9300交换机堆叠
  • matplotlib从起点出发(11)_Tutorial_11_TightLayout
  • 利用Caddy实现http反向代理
  • 网络安全深入学习第八课——代理与端口转发
  • 【FastCAE源码阅读7】视图方向切换按钮实现原理
  • 【论文阅读】多模态NeRF:Cross-Spectral Neural Radiance Fields
  • LeetCode(1)合并两个有序数组【数组/字符串】【简单】
  • k8s持久化存储PV、PVC
  • 【Ruoyi管理后台】用户登录强制修改密码
  • 分享一款快速APP功能测试工具
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • Docker: 容器互访的三种方式
  • flask接收请求并推入栈
  • golang 发送GET和POST示例
  • iOS 系统授权开发
  • JavaScript新鲜事·第5期
  • nodejs调试方法
  • React-生命周期杂记
  • Unix命令
  • Vue全家桶实现一个Web App
  • 从输入URL到页面加载发生了什么
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 来,膜拜下android roadmap,强大的执行力
  • 马上搞懂 GeoJSON
  • 突破自己的技术思维
  • 小程序开发之路(一)
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • Spring第一个helloWorld
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ###项目技术发展史
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (分布式缓存)Redis分片集群
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (三) diretfbrc详解
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (一) springboot详细介绍
  • (转) Android中ViewStub组件使用
  • (转)大型网站的系统架构
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .NET Core 中插件式开发实现
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .net经典笔试题
  • .NET设计模式(11):组合模式(Composite Pattern)
  • /etc/skel 目录作用