【数据结构初阶】环形链表

news2024/11/25 8:22:28

目录

  • 一、判断链表中是否存在环
    • 思路
    • 分析
  • 二、求环的长度
  • 三、求入环点

一、判断链表中是否存在环

题目链接:
判断链表中是否存在环

思路

把它转换为追击问题(快慢指针)
快指针比慢指针多走一步,当快指针正好进入环时,慢指针刚好走到一半;
当慢指针正好入环时,快指针在环里的位置是不确定的,可能已经绕环好几圈了,也可能一圈也没绕完,这个取决于环的长度。
快慢指针都进环后,剩下的问题就是追击问题了,当快指针追上慢指针,说明链表有环。
在这里插入图片描述

代码思路:
1.快指针比慢指针多走一步;
2.情况一:如果fast走到空,说明链表是没环的; 情况二:进环-》追击-》追上-》证明链表有环;

bool hasCycle(struct ListNode *head) 
{
    struct ListNode *slow=head;
    struct ListNode *fast=head;

    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            return true;
        }
    }

    return false;
}

在这里插入图片描述

分析

问题1:为什么slow走一步,fast走两步,他们会相遇?会不会错过?请证明:

在这里插入图片描述

假设slow进环时,fast和slow的距离为N;
slow每走1步,fast走2步
他们之间的距离每次缩小1:即N,N-1,N-2…3,2,1,0,当距离为0时就追上了;

问题2:如果slow走1步,fast走3步,他们会不会相遇?请证明:

假设slow进环时,fast和slow的距离为N;
slow每走1步,fast走3步,他们之间的距离每次缩小2:
情况一:(当N为偶数)N,N-2,N-4…4,2,0—能追上
情况二:(当N为奇数)N,N-2,N-4…5,3,1,-1—错过,设环的周长为C,此时slow和fast的距离变为C-1,
在这里插入图片描述

进入新的一轮追击:
情况一:(当C为偶数,则C-1为奇数)C-1,C-3,C-5…5,3,1,-1—错过,此时fast和slow不可能再相遇了
情况二:(当C为奇数,则C-1为偶数)C-1,C-3,C-5…4,2,0—能追上

总结:
如果slow走1步,fast走X(X>2)步,他们会不会相遇?请证明: 主要看fast和slow他们之间的每走一步相差的距离,如果相差的距离为1,则一定能追上;如果相差的距离为大于1,要分情况讨论,看他们之间的距离是奇数还是偶数;

二、求环的长度

思路:让slow和fast相遇->slow再走一圈(同时记个数)

三、求入环点

题目链接:
求入环点

方法一:(利用fast走的路程永远是slow的两倍建立等式
假设:
起始点~入口点距离为L;
入口点~相遇点距离为X(0<=X<C);(slow在相遇之前不可能走完一圈,因为fast比slow快,所以X<C;也有可能slow和fast在入口点相遇,所以X也可以是0)
环的周长:C;

在这里插入图片描述
slow走过的距离为L+X;
fast走过的距离为L+nC+X;

成立等式:fast走过的距离是slow的两倍=》L+nC+X=2(L+X)=》整理得:L=nC-X
结论:一个指针从起始点走,一个指针从入口点走,会在入口点相遇

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode *fast=head;
    struct ListNode *slow=head;
    struct ListNode *meet=NULL;
    struct ListNode *rhead=head;
    
    //找相遇点
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            //一个指针从起始点走,一个指针从相遇点走
            meet=fast;
            while(meet!=rhead)
            {
                meet=meet->next;
                rhead=rhead->next;
            }
            return meet;

        }
    }

    return NULL;
}

方法二:(找入口点,转换成找链表交点(链表相交问题)

相遇点跟相遇点的下一个节点直接断开;
一个指针从起始点开始走算长度,一个指针从相遇点的下一个节点开始走算长度,然后再让长的先走,相交的那个点就是入口点

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

int Compare(struct ListNode *circle,struct ListNode *rhead)
{
    int d1=0;
    int d2=0;

    while(circle)
    {
        circle=circle->next;
        d1++;
    }

    while(rhead)
    {
        rhead=rhead->next;
        d2++;
    }

    return d1-d2;

}



struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode *fast=head;
    struct ListNode *slow=head;
    struct ListNode *meet=NULL;

    
    //找相遇点
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            //断开结点
            slow=slow->next;
            fast->next=NULL;

            //判断哪一段长
            struct ListNode *rhead=head;
            struct ListNode *circle=slow;
            int ret=Compare(circle,rhead);

            fast=circle;
            slow=rhead;
            if(ret<0)
            {
                fast=rhead;
                slow=circle;
            }
            
            //长的先走
            int distance=abs(ret);
            while(distance)
            {
                fast=fast->next;
                distance--;
            }

            //一起走
            while(fast!=slow)
            {
                fast=fast->next;
                slow=slow->next;
            }

            return fast;

        }
    }

    return NULL;
}

在这里插入图片描述

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

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

相关文章

脑科学数据挖掘论文精读系列(1)【抑郁对大脑神经影响和对脊椎损伤患者运动恢复的影响探究】

Depression mediated the relationships between precentral-subcortical causal links and motor recovery in spinal cord injury patients 手动防爬虫&#xff0c;原创作者CSDN&#xff1a;总是重复名字我很烦啊&#xff0c;联系邮箱daledeng123163.com直达原文 这是一篇收…

操作系统——操作系统用户界面

0.关注博主有更多知识 操作系统入门知识合集 目录 3.1操作系统启动过程 3.1.1BIOS和主引导记录MBR 思考题&#xff1a; 3.1.2操作系统的启动过程 思考题&#xff1a; 3.2用户界面 3.2.1用户界面概念 思考题&#xff1a; 3.2.2系统调用 3.1操作系统启动过程 3.1.1BIO…

【五一创作】使用Resnet残差网络对图像进行分类(猫十二分类,模型定义、训练、保存、预测)(一)

使用Resnet残差网络对图像进行分类 &#xff08;猫十二分类&#xff0c;模型定义、训练、保存、预测&#xff09;(一&#xff09; 目录 一、项目简介 二、环境说明 1、安装库 2、导入需要的库 三、分类过程 &#xff08;1&#xff09;、解压数据集 &#xff08;2&#xf…

Spring中的Bean

1. Bean的配置 Spring 可以被看作是一个大型工厂&#xff0c;这个工厂的作用就是生产和管理 Spring 容器中的Bean。如果想要在项目中使用这个工厂&#xff0c;就需要开发者对Spring 的配置文件进行配置。 Spring 容器支持XML 和 Properties 两种格式的配置文件&#xff0c;在实…

【Python Web】Flask超实用基础知识总结(内附代码)

Flask是一种轻量级Web应用框架&#xff0c;使用Python编写。它是一个简单易用的框架&#xff0c;适合构建小型到中型的Web应用程序。Flask提供了基本的Web开发功能&#xff0c;如路由、请求处理、模板渲染、文件上传等。 下面是Flask的一些基础语法 文章目录 1.静态文件处理2.…

【建议收藏】计算机视觉是什么?这几个计算机视觉的核心任务你真的了解吗?

文章目录 &#x1f4da;引言&#x1f4d6;计算机视觉的核心任务&#x1f4d1;图像分类和对象识别&#x1f4d1;目标检测&#x1f4d1;语义分割&#x1f4d1;实例分割&#x1f4d1;图像生成 &#x1f4d6;计算机视觉的应用领域&#x1f4d1;人脸识别&#x1f4d1;自动驾驶&#…

【论文阅读】LORA: LOW-RANK ADAPTATION OF LARGE LAN- GUAGE MODELS

3.最近很多工作好像都绕不开lora&#xff0c;无论是sd还是llm.... 1. 背景 问题&#xff1a;大模型重新训练所有模型参数的完全微调变得不太可行。lora在做什么 我们提出了低秩自适应&#xff0c;即LoRA&#xff0c;它冻结预先训练的模型权重&#xff0c;并将可训练的秩分解矩…

高级数据结构 Trie树(字典树)

高级数据结构 Trie树&#xff08;字典树&#xff09; &#xff08;Trie Tree&#xff09;字典树_Rkun18的博客-CSDN博客 字典树节点表示 #define TRIE_MAX_CHAR_NUM 26 //这里你可以自由设置 根据不同需求设置 如果有大小或者其他符号你就需要增大这个数字struct TrieNode{T…

在amd64与arm上用paddlelite部署paddelOCR(Ascend硬件)

由于部署的硬件是华为昇腾 NPU&#xff08;Ascend310&#xff09;&#xff0c;参考网址https://www.paddlepaddle.org.cn/lite/v2.10/demo_guides/huawei_ascend_npu.html#npu-paddle-lite 先拉取paddlelite用来编译库 git clone https://github.com/PaddlePaddle/Paddle-Lit…

2. Java 异常体系

2.1 Throwable java.lang.Throwable 类是 Java 程序执行过程中发生的异常事件对应的类的根父类。 Throwable 中的常用方法&#xff1a; public void printStackTrace()&#xff1a;打印异常的详细信息。 包含了异常的类型、异常的原因、异常出现的位置、在开发和调试阶段都得…

倾斜摄影超大场景的三维模型轻量化纹理压缩的关键技术

倾斜摄影超大场景的三维模型轻量化纹理压缩的关键技术 倾斜摄影超大场景的三维模型轻量化处理中纹理压缩是轻量化处理的重要手段之一&#xff0c;可以在保证模型真实感的前提下&#xff0c;减小数据体积、降低传输带宽和提高渲染性能。以下是几个关键的纹理压缩技术&#xff1a…

自然语言处理知识抽取(pkuseg、DDParser安装及使用)

一、分词简介 1.基本概念 分词是自然语言处理中的一个重要步骤&#xff0c;它可以帮助我们将文本分成一个个词语&#xff0c;以便更好地理解和分析文本。在计算机视觉、语音识别、机器翻译等领域&#xff0c;分词都扮演着重要的角色。 目前&#xff0c;常用的分词库包括 jie…

搭建Redis主从集群+哨兵+代理predixy

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Redis是什么&#xff1f;二、搭建Redis集群步骤1.环境和版本2.Redis 安装部署3.主从同步配置4.哨兵模式配置5.代理predixy配置 总结 前言 提示&#xff1a…

深度学习 -- Dataset与DataLoader

前言 在模型训练的步骤中&#xff0c;数据的部分非常重要&#xff0c;它的过程主要分为数据收集、数据划分、数据读取、数据预处理。 数据收集的有原始样本和标签(Img&#xff0c;label) 数据集的划分需要分为训练集、验证集、测试集。 训练集负责训练模型&#xff0c;验证集…

【C++】C++11常用特性总结

哥们哥们&#xff0c;把书读烂&#xff0c;困在爱里是笨蛋&#xff01; 文章目录 一、统一的列表初始化1.统一的{}初始化2.std::initializer_list类型的初始化 二、简化声明的关键字1.decltype2.auto && nullptr 三、STL中的一些变化1.新增容器&#xff1a;array &…

趣说数据结构(练习2) —— 顺序表/链表力扣刷题(中等难度)

练习 2 —— 顺序表/链表力扣刷题&#xff08;中等难度&#xff09; 1. 反转链表 II 力扣原题&#xff1a;https://leetcode.cn/problems/reverse-linked-list-ii/ 题目描述 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从…

数据可视化大屏的页面布局以及自适应

在做数据可视化大屏之前&#xff0c;我们需要考虑到页面的布局问题以及页面缩放自适应问题&#xff0c;下面分别就这两个方面讲解。 页面布局 类似这种页面区块的明显划分&#xff0c;常用的布局方式有两种&#xff1a; 1、flex布局 2、grid布局 grid布局 grid布局可以按区块…

山东专升本计算机第二章-Windows7操作系统

Windows7操作系统 2.3Windows7的文件和文件夹管理 考点7 Windows7的基础知识 文件&#xff0c;是指存放在外存储器上的一组相关信息的•集合 文件名是操作系统中区分不同文件的唯一标志 文件名是由主文件名和扩展名两部分组成不能使用 ▏ < > * ? \ / &#xff1a; …

单向带头链表的添加修改删除操作

public class HeroNodeDemo {public static void main(String[] args) {HeroNode hero1 new HeroNode(1, "松江");HeroNode hero2 new HeroNode(2, "武松");HeroNode hero3 new HeroNode(3, "及时雨");HeroNode hero4 new HeroNode(4, "…

prometheus实战之一:用ansible部署

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 关于《prometheus实战》 《prometheus实战》是欣宸原创的系列文章&#xff0c;旨在通过实战操作来熟悉和掌握prometheus常规技能 本篇概览 本文是《promet…