【算法-链表4】环形链表2的两种解法

今天,带来链表相关算法的讲解。文中不足错漏之处望请斧正!

理论基础点这里


环形链表

1. 思路

利用链表相交

我们在环内任意一处断开,然后判断断开处的下一个位置和head是否相交,如果相交,相交处就是环口。

在这里插入图片描述

公式法

  1. 利用快慢指针判断是否有环
  2. 计算环内和环外的相交节点,即环的入口

快慢指针怎么判断是否有环?

如果有环,快指针一定先进环,慢指针后进环。都在环内后,快指针会开始追赶慢指针,最后一定会追上。为什么一定会追上呢?我们让快指针每次走两步,慢指针每次走一步,快慢指针走一次,距离就缩减一步,最终一定会追上。

环内外的相交节点为什么是环的入口?

如图,定义head到环口的距离为x,环口到快慢指针相遇点的距离为y,快慢指针相遇点到环口的距离为z。

在这里插入图片描述

slow入圈后不会转圈,在 环口 或 第二次到环口前 就直接和fast相遇,所以slow移动距离为x + y

fast可能在slow入圈前转了n圈,所以fast移动距离为x + y + n(y + z)

又因为fast的速度是slow的2倍,所以fast的移动距离也是slow的2倍:

2(x + y) = x + y + n(y + z)

其中n≥1。

x + y = n(y + z)

x = n(y + z) - y

x = (n - 1)(y + z) + z

代值,当n=1:

x = z

不管转了多少圈,从起点到环口的距离始终等于相遇处到环口的距离。

因此,我们给一个inRing和一个outRing,分别表示环内相遇处和环外头节点的位置,让他俩同步走,最后相遇位置就是环口。

为什么slow入圈后不会转圈,会在环口直接fast相遇?

难道slow入圈后不能转上几圈吗?

情况1:slow刚入圈在环口时,fast也在环口

在这里插入图片描述

这种情况slowslow不会转圈,会在环口直接和fast相遇。

情况2:slow刚入圈在环口时,fast在环内某一位置

在这里插入图片描述

当fast走了k+n的距离,slow会走(k+n) / 2的距离。因为k比n小,所以(k+n) / 2小于n。

这种情况下,fast已经走到了环口,而slow还没走到. 而fast和slow的相对距离每次只减一, 这就说明, 在环口3前,fast已经一步一步追上了slow。slow不会转圈。

综上,slow会在环口或环口前和fast相遇。

2. 参考代码

class Solution {
public:
    // 题意: 找到环口
    // 建模1: 把环内一处断开, 把环外的head 和 环内的切口 看作两个链表头, 利用链表相交来获取相交位置
    ListNode *detectCycle(ListNode *head) {
        if (head == nullptr) return nullptr;

        // 1. 找到环内一处, 断开
        ListNode *slow = head;
        ListNode *fast = head;
        ListNode *cycleCut = nullptr;
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) break;
        }
        if (slow != fast) return nullptr;
        else {
            cycleCut = slow->next;
            slow->next = nullptr;
        }

        // 2. 利用链表相交来获取相交位置
        return getIntersectionNode(head, cycleCut);
    }

private:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        // 1. 计算长度差gap
        int sizeA = getSize(headA);
        int sizeB = getSize(headB);
        int gap = abs(sizeA - sizeB);

        // 2. 长的链表先走gap步 -- 二表长度相同
        ListNode *&longList = sizeA > sizeB ? headA : headB;
        while (gap--) longList = longList->next;

        // 3. 二表同时走, 走某步时两表指针指向同一个元素就表示链表在此处相交
        while (headA != nullptr) {
            if (headA == headB) return headA;
            headA = headA->next;
            headB = headB->next;
        }

        return nullptr;
    }

    int getSize(ListNode *head) {
        int size = 0;
        while (head != nullptr) {
            head = head->next;
            ++size;
        }
        return size;
    }
};
class Solution {
public:    
    // 题意: 找到环口
    // 建模2: 公式法 -- 环内相遇处到环口的距离 = 环外head到环口的距离
    ListNode *detectCycle(ListNode *head) {
        ListNode *slow = head;
        ListNode *fast = head;
        ListNode *outRing = head;
        ListNode *inRing = nullptr;
        // 快慢指针相遇处 = 环内
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) {
                inRing = slow;
                while (inRing != outRing) {
                    inRing = inRing->next;
                    outRing = outRing->next;
                }
                return inRing; // 此时inRing和outRing已经在环口相遇                
            }
        }

        return nullptr;
    }
};

今天的分享就到这里了,感谢您能看到这里。

这里是培根的blog,期待与你共同进步!

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

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

相关文章

ArcGIS10.8 连接 PostgreSQL 及遇到的两个问题

前提 以前同事用过我的电脑连PostgreSQL,失败了。当时不知道原因,只能使用GeoServer来发布数据了。现在终于搞明白了,原因是ArcGIS10.2版本太老,无法连接PostgreSQL9.4。参考这里 为了适应时代的发展,那我就用新的Ar…

Spark的转换算子和操作算子

1 Transformation转换算子 1.1 Value类型 1)创建包名:com.shangjack.value 1.1.1 map()映射 参数f是一个函数可以写作匿名子类,它可以接收一个参数。当某个RDD执行map方法时,会遍历该RDD中的每一个数据项,并依次应用f函…

python Flask框架,调用MobileNetV2图像分类模型,实现前端上传图像分类

python Flask框架,调用MobileNetV2图像分类模型,实现前端上传图像分类 今天博主介绍一个图像分类的小项目 基于flask 和mobileNetV2模型的前端图像分类项目 环境配置如下: python版本3.7.6 安装库的版本如下: tensorflow 2.11.…

LabVIEW中NIGPIB设备与驱动程序不相关的MAX报错

LabVIEW中NIGPIB设备与驱动程序不相关的MAX报错 当插入GPIB-USB设备时,看到了NI MAX中列出该设备,但却显示了黄色警告指示,并且指出Windows没有与您的设备相关的驱动程序。 解决方案 需要安装能兼容的NI-488.2驱动程序。 通过交叉参考以下有…

STM32--时钟树

一、什么是时钟? 时钟是单片机的脉搏,是系统工作的同步节拍。单片机上至CPU,下至总线外设,它们工作时序的配合,都需要一个同步的时钟信号来统一指挥。时钟信号是周期性的脉冲信号。 二、什么是时钟树? S…

“Git实践指南:深入探索开发测试上线、分支管理与标签“

文章目录 引言一、Git的分支的使用1.分支2.标签3.分支与标签的关系4. 分支在实际中的作用5. 四个环境以及各自的功能特点6. 分支策略分支应用场景 二、Git的标签3.1 标签的基本使用3.3 标签的共享与推送 总结 引言 在现代软件开发中,版本控制是一个关键的环节&…

2023年【危险化学品经营单位主要负责人】免费试题及危险化学品经营单位主要负责人证考试

题库来源:安全生产模拟考试一点通公众号小程序 2023年危险化学品经营单位主要负责人免费试题为正在备考危险化学品经营单位主要负责人操作证的学员准备的理论考试专题,每个月更新的危险化学品经营单位主要负责人证考试祝您顺利通过危险化学品经营单位主…

【扩散模型】万字长文全面理解与应用Stable Diffusion

万字长文全面理解与应用Stable Diffusion 1. Stable Diffusion简介1.1 基本概念1.2 主体结构1.3 训练细节1.4 模型评测1.5 模型应用1.6 模型版本1.7 其他类型的条件生成模型1.8 使用DreamBooth进行微调 2. 实战Stable Diffusion2.1 环境准备2.2 从文本生成图像2.3 Stable Diffu…

LIBGDX实时绘制字符、实时绘制中文

LIBGDX实时绘制字符、实时绘制中文 转自&#xff1a;https://lingkang.top/archives/libgdx-shi-shi-hui-zhi-zi-fu 注意&#xff0c;相比于贴图字体&#xff0c;实时绘制会有一定的失真、模糊 Maven项目依赖&#xff1a; <properties><maven.compiler.source>…

抢量双11!抖音商城「官方立减」 缘何成为“爆单神器”?

10月20日抖音商城双11好物节正式开跑&#xff0c;仅仅三天&#xff0c;抖音商城整体GMV对比去年同期提升了200%&#xff0c;而在开跑一周后&#xff0c;一些品牌的销售额已经超过了今年整个618&#xff0c;可谓增势迅猛。其中&#xff0c;平台官方特别推出的「官方立减」玩法&a…

基于51单片机的篮球比赛计分器积分器

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;单片机篮球 获取完整源程序仿真源文件原理图文件论文报告等 基于51单片机的篮球计分器 由STC89C51单片机数码管显示模块按键模块电源模块构成 具体功能&#xff1a; &#xff08;1&#xff09;能记录单节比赛的比赛时间&am…

ETW HOOK原理探析

ETW HOOK研究 文章目录 ETW HOOK研究前言原理探究内核开启ETW日志HOOK ETW修改ETW日志上下文代理GetCpuClock函数寻找SSDT和SSDT Shadow 总结参考 前言 关于ETW是什么我就不多说了&#xff0c;可以通过微软的相关文档了解到。据网上得知这项技术最早被披露于2345的驱动中&…

【字符串】【双指针翻转字符串+快慢指针】Leetcode 151 反转字符串中单词【好】

【字符串】【双指针翻转字符串快慢指针】Leetcode 151 反转字符串中单词 解法1 双指针翻转字符串快慢指针更新数组大小 ---------------&#x1f388;&#x1f388;题目链接&#x1f388;&#x1f388;------------------- ---------------&#x1f388;&#x1f388;解答链接…

UI自动化测试 | Jenkins配置优化

前一段时间帮助团队搭建了UI自动化环境&#xff0c;这里将Jenkins环境的一些配置分享给大家。 背景&#xff1a; 团队下半年的目标之一是实现自动化测试&#xff0c;这里要吐槽一下&#xff0c;之前开发的测试平台了&#xff0c;最初的目的是用来做接口自动化测试和性能测试&…

MySQL 数据库查询与数据操作:使用 ORDER BY 排序和 DELETE 删除记录

使用 ORDER BY 进行排序 使用 ORDER BY 语句按升序或降序对结果进行排序。 ORDER BY 关键字默认按升序排序。要按降序排序结果&#xff0c;使用 DESC 关键字。 示例按名称按字母顺序排序结果&#xff1a; import mysql.connectormydb mysql.connector.connect(host"l…

Linux 内核定时器

一个人总要走陌生的路&#xff0c;看陌生的风景&#xff0c;听陌生的歌&#xff0c;然后在某个不经意的瞬间&#xff0c;你会发现&#xff0c;原本费尽心机想要忘记的事情真的就这么忘记了。 ----小新 一、引言 Linux内核定时器是一种用于在特定时间间隔后触发特定事件的重要组…

数据结构之AVL树

map/multimap/set/multiset这几个容器有个共同点是: 其底层都是按照二叉搜索树来实现的,但是普通的二叉搜索树有其自身的缺陷, 假如往树中插入的元素有序或者接近有序, 二叉搜索树就会退化成单支树, 时间复杂度会退化成O(N),因此map、set等关联式容器的底层结构是对二叉树进行了…

JavaScript基础入门04

目录 1.WebAPI 背景知识 1.1什么是 WebAPI 1.2什么是 API 2.DOM 基本概念 2.1什么是 DOM 2.2DOM 树 3.获取元素 3.1querySelector 3.2querySelectorAll 4.事件初识 4.1基本概念 4.2事件三要素 4.3简单示例 5.操作元素 5.1获取/修改元素内容 5.2获取/修改元素属性…

记事本简单运行java代码,理解程序运行

1.记事本创建一个文件, 把后缀.txt改为.java 如果没有显示尾缀, 勾选出文件扩展名 2.在文件里面编辑java代码并保存 3.在当前目录打开cmd 4.执行 javac Test.java 会生成好编译的.class文件 5.执行下面代码, 就成功得到j编写ava打印的代码 java Test 6.注意上面的中文在cmd中…

Windows下安装Anaconda5.3.1+Python3.8+TensorFlow2.13.0-CPU版本总结

Python3.8安装可以参考博文https://janus.blog.csdn.net/article/details/55274849 进行安装即可。 【1】Anaconda 清华的开源软件镜像站&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/下载&#xff0c;这里选择的是5.3.1版本。 然后正常安装就可以&am…