两道链表经典算法题---链表有无环(基础+进阶)

news2024/11/28 2:30:19

生活就像一盒巧克力,你永远不知道你会得到什么。——《阿甘正传》

目前自己粗略的学完数据结构,正在开始刷算法题目。个人觉得算法是一个积累,循序渐进的的过程,需要不断加量,进而达到所谓的质。

链表作为数据结构一个重要的分支。我们没有理由不学好它,并且没有理由不刷一些链表的算法题。所以,今天想和大家讲解一下链表有无存在环的经典题目,并且由这道题目本身知识点发散开来,进而来解决一道有无环的进阶题目。看完这一篇文章,你的收获一定会非常之大。看完理解其中的原理之后,你只想说:秒,牛,我靠还能这样,·······,甚至你会直接关注我,给我点个赞。

目录:

一.判断链表是否有环

1.双指针作用(铺垫)

2.结论:环形链表的环一定在末尾,末尾没有NULL

3.具体步骤思路

4.详细代码

二.链表中环的入口节点

1.思路

2.两个结论:

4.详细代码


一.判断链表是否有环

先把题目给到大家,大家可以浏览一下:

1.双指针作用(铺垫)

双指针的作用:由于单向链表(如上图)的每一个指针只能从头往后扫描,并不能从后往前的这一个局限性。所以,我们在解决单向链表的题目上,引入双指针。双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针(特殊情况甚至可以多个),两个指针或是同方向访问两个链表,或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而建立一种手段,让这种手段为我们的目的服务。


2.结论:环形链表的环一定在末尾,末尾没有NULL

证明:看上图,在环2,0,-4中,没有任何一个节点可以指出环,它们只能在环内不断循环,链表不像二叉树,每个节点只有一个val值和一个next指针,也就是说一个节点只能有一个指针指向下一个节点,不能有两个指针。因此环后面不可能还有一条尾巴。如果是普通链表末尾一定有NULL(第一个图),那我们可以根据链表中是否有NULL判断是不是有环。

3.具体步骤思路

  • step 1:设置快慢两个指针,初始都指向链表头。

  • step 2:遍历链表,快指针每次走两步,慢指针每次走一步。

  • step 3:如果快指针到了链表末尾,说明没有环,因为它每次走两步,所以要验证连续两步是否为NULL。

  • step 4:如果链表有环,那快慢双指针会在环内循环,因为快指针每次走两步,因此快指针会在环内追到慢指针,二者相遇就代表有环。

·对于step4的进一步解释(个人理解):我们可以这样想,这个快指针一次是走两步,然后慢指针一次走一步,两指针距离会拉大,每循环一次两个指针的距离就会+1,我们假设在遇到环的那一刻他们之间的距离就是n,这时候慢指针在后面,快指针在这个环做周期性走动,慢指针就一步一步的跟上这个快指针,也就是这个n以减1的速度一直在靠近0,直到n=0,这个时候快慢指针就相遇。就能够判断链表有环。

画图解释,看下图:

快指针走两步,慢指针走一步,最后相遇。一步一步分析。

4.详细代码

前面都是理论,接下来用代码实现:

#include <stdbool.h>

 struct ListNode {
  int val;
  struct ListNode *next;
 };//定义一个结点
bool hasCycle(struct ListNode* head )/返回类型是bool 
{
   struct  ListNode*fast=head;
   struct ListNode*slow=head;
   while(fast!=NULL&&fast->next!=NULL)
   {
    fast=fast->next->next;//快指针走两步
    slow=slow->next;//慢指针走一步
    if(slow==fast)//如果相遇,则有环
    {
        return true;
    }
   }
   return false;  
}

二.链表中环的入口节点

在上一道题目的基础上,我们再来搞定这一道进阶题目:

1.思路

设置快慢指针,都从链表头出发,快指针每次走两步,慢指针一次走一步,假如有环,一定相遇于环中某点(结论一)。接着让两个指针分别从相遇点和链表头出发,两者都改为每次走一步,最终相遇于环入口(结论二)。以下是两个结论证明:

2.两个结论:

结论一:设置快慢指针,假如有环,他们最后一定相遇。

证明:设置快慢指针fast和slow,fast每次走两步,slow每次走一步。假如有环,两者一定会相遇(因为slow一旦进环,可看作fast在后面追赶slow的过程,每次两者都接近一步,最后一定能追上)。也即第一道题的结论。

结论二:两个指针分别从链表头和相遇点继续出发,每次走一步,最后一定相遇与环入口。

证明:设:

链表头到环入口长度为--a

环入口到相遇点长度为--b

相遇点到环入口长度为--c

则:相遇时

快指针路程=a+(b+c)k+b ,k>=1 其中b+c为环的长度,k为绕环的圈数(k>=1,即最少一圈,不能是0圈,不然和慢指针走的一样长,矛盾)。

慢指针路程=a+b

快指针走的路程是慢指针的两倍,所以:

(a+b)*2=a+(b+c)k+b

化简可得:

a=(k-1)(b+c)+c 这个式子的意思是: 链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈环长度。其中k>=1,所以k-1>=0圈。所以两个指针分别从链表头和相遇点出发,最后一定相遇于环入口。

4.详细代码

前面都是理论,接下来用代码(C++)实现:

class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        ListNode*fast=pHead;
        ListNode*slow=pHead;
        while(fast!=nullptr&&fast->next!=nullptr)
        {
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)
            break;
        }
        if(!fast||!fast->next)return nullptr;
        slow=pHead;
        while(slow!=fast)
        {
            fast=fast->next;
            slow=slow->next;
        }
        return slow;

    }
};

以上是两道很经典的题目,就讲解到这里。

哦,对了,刚刚在构思这篇文章的过程中突然想到今天是情人节,然后然后,脑子里突然想起,正在看这篇文章的你可能你还没对象,所以呢哈哈哈,下一篇文章要讲解关于C++中new这类知识点,最后new一个自己想要的理想对象致敬在座的每个人。关记得关注我,下一篇今晚就发。

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

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

相关文章

全网详解MyBatis-Plus LambdaQueryWrapper的使用说明以及LambdaQueryWrapper和QueryWapper的区别

文章目录1. 文章引言2. 代码演示3. 分析LambdaQueryWrapper3.1 引入LambdaQueryWrapper的原因3.2 LambdaQueryWrapper和QueryWapper的区别4. 重要总结1. 文章引言 今天在公司写代码时&#xff0c;发现同事使用LambdaQueryWrapper来查询数据&#xff0c;而我一直习惯使用QueryW…

没对比没伤害,浙江男不买包包被女友拖拽,深圳男收三个女孩红包

又是一年一度的情人节&#xff0c;虽然这只是一个西方的节日&#xff0c;却被中国的商人们充分利用&#xff0c;也造成了不小的社会矛盾。在今年的情人节里&#xff0c;浙江就发生了一件奇葩的事情&#xff0c;一位女子因不满其男友 不给自己买两万元包包&#xff0c;就在商场里…

Onvif协议如何判断摄像机支持 —— 筑梦之路

有人就问什么是Onvif协议呢&#xff1f; 全称为&#xff1a;Open Network Video Interface Forum.缩写成Onvif。 翻译过来是&#xff1a;开放型网络视频接口论坛&#xff0c;目的是确保不同安防厂商的视频产品能够具有互通性&#xff0c;这样对整体安防行业才是良性发展。 现…

【C语言编译器】01程序-编译器-IDE

目录一、程序的几个基本概念二、什么是编译器三、集成开发环境3.1 IDE简介3.2 windows 下的C语言IDE一、程序的几个基本概念 计算机程序&#xff08;Computer Program&#xff09;&#xff1b;港、台译做电脑程式。计算机程序是一组计算机能识别和执行的指令&#xff0c;运行于…

5 款最好的免费 SSD 数据恢复软件

SSD&#xff08;固态硬盘&#xff09;提供比传统硬盘更快的读/写速度&#xff0c;使启动、软件加载和游戏启动更快。因此&#xff0c;在我们选择存储设备时&#xff0c;它是一个极好的选择。但是&#xff0c;它仍然存在数据丢失的风险。假设您是受害者之一&#xff0c;正在寻找…

SpringBoot的创建和使用

SpringBoot是什么&#xff1f;SpringBoot诞生的目的就是为了简化Spring开发&#xff0c;而相对于Spring&#xff0c;SpringBoot算是一个很大的升级&#xff0c;就如同汽车手动挡变成了自动挡。Spring&#xff1a;SpringBoot&#xff1a;SpringBoot的优点SpringBoot让Spring开发…

[技术选型] ClickHouse和StarRocks的介绍

文章目录1.ClickHouse介绍2.StarRocks介绍1.ClickHouse介绍 ClickHouse是面向联机分析处理&#xff08;OLAP&#xff09;的开源分析引擎。最初由俄罗斯第一搜索引擎Yandex开发&#xff0c;于2016年开源&#xff0c;开发语言为C。由于其优良的查询性能&#xff0c;PB级的数据规…

Linux的ACL(扩展权限)规划:setfacl、getfacl

目录 什么是ACL与如何支持启动ACL ACL设置技巧&#xff1a;getfacl、setfacl getfacl命令用法 setfacl命令用法 最简单的【u&#xff1a;账号&#xff1a;权限】设置 使用默认权限设置目录未来文件的ACL权限继承 什么是ACL与如何支持启动ACL ACL是Access Control List的…

【基础篇】7 # 队列:队列在线程池等有限资源池中的应用

说明 【数据结构与算法之美】专栏学习笔记 什么是队列&#xff1f; 队列是一种操作受限的线性表数据结构&#xff0c;特点是先进先出&#xff0c;最基本的操作有&#xff1a;入队 enqueue()&#xff0c;放一个数据到队列尾部&#xff1b;出队 dequeue()&#xff0c;从队列头…

综合保税区快速发展,卖家抓紧瞄准跨境电商

综合保税区指的是我国设立在内陆地区的海关特殊监管区域&#xff0c;具有报税港区的功能&#xff0c;这是由海关参照有关规定对综合保税区进行管理&#xff0c;执行保税港区的外汇政策和税收&#xff0c;集合众多功能于一身&#xff0c;包括保税区、保税物流区、出口加工区、港…

JNI开发之-CMake方式调用第三方so

CMake方式调用第三方so背景CMake工程配置工程配置配置CMakeLists.txt配置build.gradle调用第三方so中的方法背景 最近一个项目是对接自研团队的个so库&#xff0c;因为之前都是用ndk来编译自己的so库&#xff0c;一直没有问题&#xff0c;但是用到这个自研的的so库一直有问题&…

usbmon+tcpdump+wireshark USB抓包

文章目录usbmon抓包及配合wireshark解析usbmon抓包及配合wireshark解析 usbmon首先编译为内核模块&#xff0c;然后通过modprobe usbmon加载到linux sys文件系统中 rootroot-PC:~# modprobe usbmon​ 而后 linux系统下安装 tcpdump rootroot-PC:~# apt-get install tcpdump​…

如何开发一个好用的公共组件

写在前面 当你对某一个业务场景有自己的理解&#xff0c;想提炼开发了一个很好用的组件&#xff0c;想开放给别的同学使用&#xff0c;或者甚至放在社区给任何一个人使用&#xff0c;你应该会产生以下疑问&#xff1a; 一个标准的组件是怎么样的&#xff0c;在开发过程中有哪…

android-java同步方法和异步方法

接口 Java接口是一系列方法的声明&#xff0c;是一些方法特征的集合&#xff0c;一个接口只有方法的特征没有方法的实现&#xff0c;因此这些方法可以在不同的地方被不同的类实现&#xff0c;而这些实现可以具有不同的行为&#xff08;功能&#xff09;。 两种含义&#xff1a…

中文编程发展不起来,无代码开发能否打个翻身仗

中文编程夹缝里生存众所周知&#xff0c;易语言开创了中文编写程序的先河&#xff0c;最早可追溯到2000年。当时易语言风靡一时&#xff0c;背后积攒了大批的用户&#xff0c;承载着那一代人的青春。也帮助了很多普通的初学者能够在短时间的入门。如今的易语言早已失去了往日的…

大咖说·图书分享|狼书(卷3):Node.js高级技术

Node.js都有哪些需要掌握的高级技术&#xff1f;前端为什么同样需要学习&#xff1f; Node.js未来的发展趋势究竟如何&#xff1f;本期大咖说&#xff0c;Node布道师桑世龙携新作《狼书(卷3)&#xff1a;Node.js高级技术》展开分享。 ● 嘉宾介绍 桑世龙&#xff1a;Node布道…

博客系统 SSM 超强硬核良心推荐之第一弹 - 预备工作

硬核 ! 从 0 到 1 完美实现 SSM 版本的博客系统 , 学会保准不吃亏!一 . SSM 版本相比于 Servlet 版本的亮点二 . 初始化数据库三 . 前端页面3.1 注册页面3.2 登录功能3.3 文章总列表页3.4 自己的文章列表页3.5 文章详情页3.6 编写博客页面大家好 , 这是新的专栏 , 博客系统 SSM…

嵌入式Linux学习经典书籍-学完你就是高手

很多刚入门的朋友一直都有人问我要学习资料&#xff0c;嵌入式实在太杂&#xff0c;网上很多人写的太不负责了&#xff0c;本书单综合了本人以及一些朋友多年的经验整理而成。 本人见识和阅读量有限&#xff0c;本书单可能有不对的地方&#xff0c;欢迎朋友指正&#xff0c;交…

SCI写作,一定要避开这些“雷点”!

SCI论文写作中&#xff0c;除了要符合各部分的写作要求&#xff0c;还有许多细节问题需要我们注意&#xff0c;不然可能一不小心就会“踩雷”。 今天我们就来和大家分享SCI各个部分写作时的注意事项。 下面就进入正题&#xff01; SCI写作注意事项 01 标题的拟定 1.避免使用无…

[Vivado那些事儿]将自定义 IP (HDL)添加到 Vivado 模块设计(Block Design)

绪论使用Vivado Block Design设计解决了项目继承性问题&#xff0c;但是还有个问题&#xff0c;不知道大家有没有遇到&#xff0c;就是新设计的自定义 RTL 文件无法快速的添加到Block Design中&#xff0c;一种方式是通过自定义IP&#xff0c;但是一旦设计的文件有问题就需要重…