【算法专题--链表】环形链表--高频面试题(图文详解,小白一看就会!!)

目录

一、前言

 二、什么是环形链表?

🥝 环形链表的概念详解

🍇 环形链表的特点 

 🍍环形链表的延申问题

 三、高频面试题

 ✨环形链表

 ✨环形链表II

 ✨环形链表的环长

 四、总结

五、共勉 


一、前言

        环形链表,可以说是--链表专题--,最经典的一种结构,也是在面试中频率最高的一道题目,通常在面试中,面试官可能会根据环形链表的结构延申出很多问题,所以大家需要对这环形链表结构非常熟悉哦!!
      本片博客就来详细的讲讲解一下
环形链表,让我们的面试变的更加顺利!!!

 二、什么是环形链表?

🥝 环形链表的概念详解

       环形链表是一种特殊类型的链表数据结构,其最后一个节点的"下一个"指针指向链表中的某个节点,形成一个闭环。 换句话说,链表的最后一个节点连接到了链表中的某个中间节点,而不是通常情况下连接到空指针 (null) 
       如果大家对链表还不熟悉可以先看看这篇文章:单链表详解

🍇 环形链表的特点 

 特点:
1️⃣:若一个链表带环,那么用指针一直顺着链表遍历,最终会回到某个地方。
2️⃣:  我们可以定义两个指针(快慢指针),两个指针均从表头开始同时遍历链表,快指针一次走两步,慢指针一次走一步。如果链表带环,那么快慢指针一定会相遇,否则快指针会先遍历完链表(遇到NULL)。

  • 若是你不明白为什么链表带环,快慢指针就一定会相遇,那么你可以想想龟兔赛跑: 

 🍍环形链表的延申问题

 1️⃣:为什么慢指针走一步快指针走两步,他们一定会在环里面meet吗?会不会永远追不上?

  •   首先 慢指针快指针一定是快指针先进环
  •  随着慢指针进环快指针已经在环了走了一段距离,走了多少和环的大小有关
  •  假设慢指针进环的时候距离快指针距离为 N快指针开始追慢指针
  •  在追击过程中,快指针往前走两步慢指针往前走一步每走一次它们之间的距离就缩小 1 
  •  它们之间的距离变化为 N ,N-1 ,N-2 , . . . 1 ,0  ,它们之间的距离为 零 就会相遇所以一定追得上

 2️⃣: 为什么一定是 慢指针走一步快指针走两步?快指针能走其它步数吗?

  •  假设慢指针进环的时候,快指针慢指针之间的距离为 N
  •  在追击的时候,快指针走三步慢指针走一步,每走一次,它们之间的距离缩小 2

 此时分两种情况:

  • N 偶数,则它们之间的距离会减少到 0 相遇
  • N奇数,则它们之间的距离会减少到1 然后减少到 -1减少到 -1 也就意味着它们之间的距离又变为 C - 1 (C是环的周长)

此时又分两种情况:

  •  若 C奇数 ,则 C - 1 为偶数 ,因为它们之间的距离一次缩短 2 所以它们会相遇
  •  若 C 偶数 ,则 C - 1 为奇数 ,也就是说它们之间的距离还是奇数,它们永远不会相遇

 由此可以得出结论:快指针一次不走两步,存在追不上的情况。
 所以 必须 ---- 每次慢指针走一步 , 快指针走两步


3️⃣ :如何才能得知 环口 的节点是哪一个呢?

  •  追上的相遇的过程中,慢指针的距离:L+X快指针的距离:L+NC+X
  • 由于不知道 快指针 在环里多跑了几圈,所以设了一个N,但是N肯定>=1, 
  • 因为快指针是满指针的两倍,所以2(L+X)=L+NC+X。整理可得   L= NC - X

     至此,我们发现链表头到环入口的距离 相遇点到环入口的距离 C-X 相差 N 个环的长度。
 
  结论:一个指针指向链表头,一个指针指向第一次相遇点 , 并使两个指针的速度都为 1 ,一直前进直到它们相遇,第二次相遇的位置一定为环的入口位置。

 三、高频面试题

 ✨环形链表

题目链接:141. 环形链表 - 力扣(LeetCode) 

解题思路: 

  • 我们可以使用快慢指针法。定义步长为2的快指针步长为1的慢指针遍历链表。我们假设链表如果存在环,则快慢指针在某一时刻一定会在环内相遇;而如果不存在环,由于快指针速度比慢指针快,因此它们永远无法相遇。

 代码:

class Solution {
public:
    // 题目已经给出了 单链表的 节点构造

    bool hasCycle(ListNode *head) 
    {
        // 定义两个快慢指针
        ListNode* slow = head;    //  每次走一步
        ListNode* fast = head;    //  每次走两步

        // 当链表 有环存在时 fast 和 fast-next 一定不会指向空
        // 当快指针不为空且其下一个节点也不为空时,继续循环
        while(fast!=nullptr && fast->next!=nullptr)
        {
            slow = slow->next;
            fast = fast->next->next;
            // 相交成环
            if(slow == fast)
            {
                return true;
            }
        }
        return false;
    }
};

  疑问:为什么循环的结束条件是fast或者fast->next指向NULL?

  • 当一个链表中有环时,fast和fast->next永远不会指向NULL
  • 当一个链表中没有环时,fast一定会移动到链表的结尾;又因为fast一次移动两个节点,所以有两种情况:①fast移动两次后,刚好指向NULL,结束循环;②fast移动一次后就已经指向NULL,此时再进行移动,就会出现对NULL的解引用

 ✨环形链表II

 题目链接:142. 环形链表 II - 力扣(LeetCode)

解题思路: 

  • 起初快指针速度为2,慢指针速度为1,如果快慢指针没有相遇,则返回NULL代表不存在环;如果相遇了,我们就让 其中一个指针重新指向链表头,并使 两个指针的速度都为1,一直前进直到它们相遇,相遇的位置一定为环的位置。这是因为从 相遇点走 L 步后的位置与走C - X 步后的位置一致。

代码: 

class Solution {
public:
    ListNode *detectCycle(ListNode *head) 
    {
        // 初始化两个指针,快指针fast和慢指针slow,都指向链表头节点
        ListNode* slow = head;
        ListNode* fast = head;


        // 当快指针和其下一位都不为空时(即未到达链表尾部)
        while(fast&&fast->next)
        {
             // 慢指针每次前进一步
             slow = slow->next;
             // 快指针每次前进两步
            fast = fast->next->next;

            // 如果两个指针第一次相遇
            while(slow==fast)
            {
                // 将相遇的节点赋值给 meet变量
                ListNode* meet = fast;

                // 从头节点开始,另一个指针从相遇点开始,两者每次各前进一步
                // 直到两个指针再次相遇,相遇点即为环的起始节点
                while(head!=meet)
                {
                    head = head->next;
                    meet = meet->next;
                }

                // 返回找到环的入口节点
                return meet;
            }
        }

        return NULL;
    }
};

✨环形链表的环长

题目描述: 
给定一个链表的头节点 head ,返回链表环中环的长度。 如果链表无环,则返回 0。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。

解题思路: 

  • 我们同样可以先使用快慢指针判断链表是否存在环,当二者第一次相遇时说明链表存在环。而当快慢指针相遇后我们再次让快慢指针进行追逐战,此时它们之间的距离为环长 C,由于每次追逐它们的距离都会缩短1,因此我们可以定义一个计数器count记录第二次相遇时所追逐的次数即为链表的环长。具体过程如下:

代码: 

 struct ListNode {
    int val;
    struct ListNode* next;
    
};
int CycleLength(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) //第一次相遇,存在环
        {
            //统计第二次相遇所追逐的次数
            int count = 0;
            do
            {
                fast = fast->next->next;
                slow = slow->next;
                count++;
            } while (fast != slow);
            //相遇了,返回追逐次数即为环长
            return count;
        }
    }
    //不存在环,返回0
    return 0;
 
}

 四、总结

         以上就是今天要讲的内容,做题的时候,就是奔着双指针的思路进行解决的,练习这么多次现在逐渐找到了点感觉。我感觉就是双指针的关键点就是在于该怎么去移动两个指针,理清这一点之后离结果也就不远了,判断链表是否有环应该是老生常谈的一个话题了,最简单的一种方式就是快慢指针。慢指针针每次走一步,快指针每次走两步,如果相遇就说明有环,如果有一个为空说明没有环。所以就赶紧记录一下这时刻。

五、共勉 

     以下就是我对 环形链表 的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对 链表专题 的理解,请持续关注我哦!!! 

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

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

相关文章

单臂路由的配置(思科、华为)

#交换设备 不同vlan属于不同广播域,不能互相通信,他们配置的是不同网段的IP地址,针对不同网段的IP地址进行通信,就需要用到路由技术 实现不同vlan之间的通信技术有两种 单臂路由三层交换 单臂路由 一、思科设备的单臂路由配…

Understanding Diffusion Objectives as the ELBO with Simple Data Augmentation

Understanding Diffusion Objectives as the ELBO with Simple Data Augmentation 引言 本文前作 VDM 已经推导出了扩散模型可以将优化 ELBO 作为目标函数。然而现在 FID (也就是感知质量)最好的模型还是用的其他目标函数(如 DDPM 的噪声预…

矩阵LU分解的应用

矩阵LU分解在机器学习和深度学习中的应用广泛,主要用于解决以下问题: 线性方程组求解:LU分解可以有效地解决线性方程组,这在训练模型时非常有用。矩阵求逆:在一些机器学习算法中,需要进行矩阵求逆操作&…

二维鱼游CFD代码

最近学了会Julia,参考了原作者的shark,做一下基于airfoils 2D的鱼游,暂时没想好有什么需要深入研究的,代码公开如下: 鱼身是naca0016,然后一些参数可以参考我以前发的论文。 using WaterLily, StaticArra…

46.django - 多语言配置

1.Django 多语言基础知识 多语言站点可以让不同语言的用户更好地使用和理解网站内容,提升用户体验和覆盖范围。为了实现多语言功能,我们将使用Django内置的国际化和本地化支持。我收集了一些知识点整理在这一部分,感兴趣的可以看看。直接跳过…

k8s面试题大全,保姆级的攻略哦(三)

目录 1、简述ETCD及其特点? 2、简述ETCD适应的场景? 3、简述什么是Kubernetes? 4、简述Kubernetes和Docker的关系? 5、简述Kubernetes中什么是Minikube、Kubectl、Kubelet? 6、简述Kubernetes常见的部署方式? 7、简述Kubernetes如何实现集群管理? 8、简述Kubern…

双指针数组问题

删除有序数组中的重复项 重点在于p1 class Solution {public int removeDuplicates(int[] nums) {if(nums.length0) return 0;int p10,p21;while(p2<nums.length){if(nums[p2]!nums[p1]){nums[p1]nums[p2];}else p2;}return p11;} } class Solution {public void moveZeroe…

tkinter+火山引擎+python实现语音识别聊天机器人

想要做一款能通过语音识别来聊天的智能机器人,首先需要能通过麦克风录制语音进行识别转换成文字,将文字发送给机器人得到聊天结果,并能将返回的文字转换成语音进行合成,之后再通过本地播放语音实现语音交互。 架构: 实现步骤 一、本地录音 本地录音可以通过pyAudio库实…

【机器学习】Qwen2大模型原理、训练及推理部署实战

目录​​​​​​​ 一、引言 二、模型简介 2.1 Qwen2 模型概述 2.2 Qwen2 模型架构 三、训练与推理 3.1 Qwen2 模型训练 3.2 Qwen2 模型推理 四、总结 一、引言 刚刚写完【机器学习】Qwen1.5-14B-Chat大模型训练与推理实战 &#xff0c;阿里Qwen就推出了Qwen2&#x…

半年了,3588来了

端午两天&#xff0c;LAB1964又搞了新东西&#xff0c;RK3588&#xff0c;已经算是千呼万唤始出来&#xff0c;等的时间也是足够久了。 ——价格贵 RK3588 是真的贵&#xff0c;实验室老板贴了10片3588套片&#xff0c;就花了将近4000块钱&#xff0c;所以说&#xff0c;决定要…

kali2022安装教程(附安装包)

第一步&#xff1a;下载镜像文件 百度网盘下载https://pan.baidu.com/s/1efRQGFTbq6Kgw9axLOmWzg?pwdemxf 第二步&#xff1a;打开Vmware 第三步&#xff1a;进行各项配置 创建新的虚拟机&#xff0c;选择高级&#xff0c;然后下一步 直接默认下一步 选择稍后安装然后下…

CleanMyMac2028永久破解版苹果mac电脑垃圾清理软件

CleanMyMac&#xff0c;这款苹果mac电脑垃圾清理软件简直就是我的救星啊&#xff01;以前总是被电脑上的各种垃圾文件困扰&#xff0c;不知道如何彻底清理。自从用了CleanMyMac&#xff0c;我的电脑就像重新获得了新生一样&#xff01; 它的功能强大到让我惊叹不已&#xff01;…

一周学会Django5 Python Web开发 - Django5内置Auth认证系统-用户注销实现

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计60条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

对称加密系统解析

目录​​​​​​​ 1.概述 2. 对称密码类型 3. 对称加密优缺点 4. 对称加密算法 4.1 DES 4.2 3DES 4.3 AES ​​​​​​4.4 SM1 4.5 SM4 1.概述 对称加密&#xff0c;是指在加密和解密时使用同一秘钥的方式。秘钥的传送和保存的保护非常重要&#xff0c;务必不要让秘…

Nginx04-Nginx代理、反向代理实验、LNMP流程详解与排错思路

目录 写在前面Nginx04LNMP流程详解Nginx处理静态资源流程Nginx处理动态资源流程 LNMP排错LinuxNginxPHPMysql Nginx 代理概述正向代理反向代理区别 反向代理实验&#xff08;Proxy模块&#xff09;环境准备front配置lb01配置测试流程梳理总结 写在前面 这是Nginx第四篇&#xf…

Web 自动化测试(基于Pytest极简)

Pytest 初体验 在使用 Python 进行 Web UI 自动化测试时&#xff0c;我们除了使用 unittest 单元测试框架&#xff0c;还可以使用 pytest&#xff0c;本节实验就给大家简单的介绍一下 pytest。 环境配置 本系列实验我们借助 VS Code 工具编写代码&#xff0c;使用的 Python …

MySQL: 表的增删改查(基础)

文章目录 1. 注释2. 新增(Create)3. 查询(Retrieve)3.1 全列查询3.2 指定列查询3.3 查询字段为表达式3.4 别名3.5 去重: distinct3.6 排序: order by3.7条件查询3.8 分页查询 4. 修改 (update)5. 删除(delete)6. 内容重点总结 1. 注释 注释&#xff1a;在SQL中可以使用“–空格…

【自动部署】4.阿里云ECS服务器 IDEA自动部署项目

如何在IDEA中&#xff0c;自动部署项目到阿里云ECS服务器&#xff1f;今天我们就来实现一键部署功能。 执行maven命令打包免密登录&#xff0c;在IEDA中连接服务器执行stop脚本上传jar包到服务器执行start脚本查看运行日志 1.安装Alibaba Cloud Toolkit 2.配置host 3.自动化部…

VSCode超过390万下载的请求插件

Thunder Client 是一款在 VSCode&#xff08;Visual Studio Code&#xff09;中非常受欢迎的 REST API 客户端插件&#xff0c;由Ranga Vadhineni开发&#xff0c;现在已经有超过390万的下载量。它允许开发者直接在编辑器内发送 HTTP 请求&#xff0c;查看响应。Thunder Client…

【C++】函数模板和类模版

目录 前言 模板参数 类型模板参数 非类型模板参数 模板的特化 函数模板的特化 类模板的特化 全特化 偏特化 模板的分离编译 模板总结 前言 函数模板和类模板是C模板编程中的两个核心概念&#xff0c;它们允许程序员编写泛型代码&#xff0c;这些代码可以在多种数据…