首页 > 其他分享 >LeetCode-环形链表、环形链表 II

LeetCode-环形链表、环形链表 II

时间:2024-07-17 20:54:29浏览次数:18  
标签:II slow ListNode 相遇 fast 环形 链表 节点 指针

一、环形链表

. - 力扣(LeetCode)

判断是否有环,使用快慢指针,开始时都指向头节点,快指针每次走两部,慢指针每次走一步,如果在走的过程中,慢指针和快指针相同(也就是快指针和慢指针指向的节点的同)那么就说明这个链表是带环链表;

原理: 

若是这个链表代换,那么快慢指针一定不会走向NULL;只会在这个链表里面循环走下去,并且当循环条件允许时都会进环;同时快指针走的每次都比慢指针多一步,若是一直走下去 ,虽说快指针开始一直在慢指针前面,但是每次快指针都多走一步,最后快指针一定会和慢指针相遇,(就像跑步速度相异的两人在环形跑道上面跑步同理,开始时快的再前面,可能一圈或是两圈之后,跑的快的一定会和跑的慢的相遇)

因此,我们可以把快慢指针相遇作为判断链表是否带环的判断准则,当快慢指针相遇,就说这个链表带环;

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {
    
    ListNode* fast=head,*slow=head;

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

当头节点为NULL,或者是头节点只有一个且这个节点的next为NULL时,不进入循环,直接返回false,可见这种情况也能兼容。

当fast每次走三步或者是更多步呢?(题外话)

先看快指针每次走三步的情况:假设有环,经过上面解法可知,快慢指针相遇一定在环内部;所以我们研究在环中的过程,当慢指针进环的时候快指针已经在换里面走了一会了,我们并不清楚它走了几圈或是多远;假设环可以容纳的节点个数是C(环的长度),假设慢指针刚刚进入环的时候距离环内快指针的距离是N,那么每走一步快慢指针之间的距离就减少2,若是N是偶数,那么快慢指针就能相遇;

若是N是奇数,那么快指针在接近慢指针时相遇的距离是奇数,但是两者每次距离减少偶数2,所以快指针会追上慢指针,并且多出慢指针一个节点的距离;进入第二轮,在环中此时两者之间的距离是(C-1);若是(C-1)是偶数,那么快慢指针最终会相遇;若是(C-1)是奇数,那么会出现和第一轮相同的情况:快指针多出慢指针一个节点的距离,此时两者之间的距离又变成了(C-1);而已知(C-1)是奇数,后面的都是同样如此,这样看来似乎快慢指针永远都不会相遇;

但其实不然:

上面快慢指针不会相遇的情况出现在该条件之下:当N是奇数的时候,C是偶数;这种条件真的存在吗?假设头节点距离进环节点的距离是L,研究慢指针刚刚进环的时刻;此时慢指针走了L,假设快指针在环内走了x圈,那么快指针走的总路程就是L+x*C+N(N是慢指针刚刚进入环的时候与快指针之间的距离),同时又因为快指针走的距离是慢指针的三倍,那么就有以下等式

3*L=L+x*C+N ;

2*L=x*C+N

带入快慢指针永远不会相遇的条件:N是奇数的时候,C是偶数;

因为2*L永远是偶数,而条件带入之后,等式右边无论x是几,等式右边的最终结果都是奇数

由此可知,这种条件不会存在;当快指针每次走的步数更多得到时候,也同样如此;也就是说快慢指针一定会相遇。 


二、环形链表 II

. - 力扣(LeetCode)

 本题思路:首先判断是否带环,若是不带环就返回NULL;若是带环则返回开始进环时的那个节点指针;判断带环与否参照上一题环形链表;而对于返回进环节点指针,使用下述方法:在判断完带环与否之后我们可以得知快慢指针相遇的节点,记录下这个相遇节点,设置一次循环,让头节点从头开始遍历,相遇节点从相遇的节点开始遍历,若是两个节点相同,那么这两个节点相遇时的节点就是进环时的节点;

原理:

假设进环时的节点和头节点之间的距离是L,fast和slow指针相遇的节点距离进环节点之间的距离是N,,快慢指针相遇之后快指针在环中走了x圈,环的长度是C,把快慢指针相遇的节点称为相遇节点;找等式关系,快指针每次走两步,慢指针每次走一步,快慢指针相遇之后,快指针走的距离是慢指针的两倍,慢指针走了L+N,快指针走了L+x*C+N ;那么就有

2*(L+N)=L+x*C+N;

L+N=x*C;

L=x*C-N;

L=(x-1)*C+C-N;

 得出这个关系就说明这种方法可以找到进环节点,解释:L是头节点距离进环节点的距离,头节点从头走起,相遇节点从快慢指针相遇的节点走起,两者每次都走一步,头节点走L时,相遇节点也走了L,也就是(x-1)*C+C-N;不用管(x-1)*C,因为走完(x-1)*C之后回到相遇节点,重点是C-N,我们已知相遇节点和进环节点之间的距离是N,这时已经走过的,未走过的是C-N,那么相遇节点的最后相当于走了C-N,刚好到进环节点;

所以可以利用头节点和相遇节点一起开始遍历、找出两者相同的节点的方法得出进环节点;

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) {
    ListNode* fast=head,*slow=head;
    int flag=-1;
    
    while(fast && fast->next && slow)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(fast==slow)
       {
            flag=1;
            break;
       }
    }
    if(flag==-1)
        return NULL;

    while(head!=slow)
    {
        head=head->next;
        slow=slow->next;
    } 
    return head;
}

标签:II,slow,ListNode,相遇,fast,环形,链表,节点,指针
From: https://blog.csdn.net/zc331/article/details/140460017

相关文章

  • IIC初了解
    引脚说明IIC需要俩根引脚可以实现通信,一根是SDA(SerialData),另一根是SCL(SerialClock)所有通过IIC接口通信的外围器件都挂载到IIC总线上。IIC的总线必须有主器件提供。每个从器件由于没有片选引脚,所以每个从器件都需要有自己独立的器件地址。SDA引脚和SCL的输出模式一般都要输......
  • 串口、IIC、SPI的优缺点
    串口、IIC、SPI的优缺点串口(SerialPort)串口通信是一种基本的串行通信方式,它通过串行数据线(TX和RX)进行数据的发送和接收。串口通信通常用于微控制器与PC或其他设备之间的通信。特点:简单易用,硬件实现成本低。通信速率较低,适合长距离通信。可以实现全双工通信(同时发送和接收......
  • 机器学习 -> Machine Learning (III)
    1对抗学习对抗学习的目的是增加鲁棒性。对抗生成网络(GAN)包括生成器(Generator)和判别器(Discriminator)。如果目标是创建能够生成新内容的系统,那么生成器是希望得到并优化的模型,这是一个零和问题。1.1GenBGenB是对抗网络用于VQA的产物,如图添加了偏置模型和目标模型。训练......
  • 多种模块格式,包括 ES, CommonJS, UMD, AMD, SystemJS 和 IIFE的区别点分别是什么
    【转】https://zhuanlan.zhihu.com/p/668530823以下是各种模块格式的主要特点:ESModules(ESM):这是ECMAScript6(ES6)引入的官方标准格式。它支持导入和导出语句,以及静态分析和tree-shaking。它是唯一的静态模块系统,意味着你可以在编译时确定导入和导出的内容。CommonJS(C......
  • 大语言模型无法理解链表 Large Language Models Fails to Understand Chained Table[u
    大模型可以翻转链表,但是只能翻转单个元素链表。一但牵扯到分组操作,就不会了。Case:以K个元素为一组位翻转链表,每一组内部元素顺序不变。ReversethechainedtableingroupofKelements,don'tchangetheorderineachgroup. Handwritten: 1classNode():2......
  • 代码随想录算法训练营第26天 | 回溯02:39. 组合总和、40.组合总和II、131.分割回文串
    代码随想录算法训练营第26天|回溯02:39.组合总和、40.组合总和II、131.分割回文串组合总和https://leetcode.cn/problems/combination-sum/代码随想录https://programmercarl.com/0039.组合总和.html40.组合总和IIhttps://leetcode.cn/problems/combination-sum-ii/desc......
  • 力扣刷题练习九 【234.回文链表】
    前言链表练习题【234.回文链表】。回顾链表知识,做题练习。一、【234.回文链表】题目阅读给你一个单链表的头节点head,请你判断该链表是否为回文链表。如果是,返回true;否则,返回false。示例1:输入:head=[1,2,2,1]输出:true示例2:输入:head=[1,2]输出:false......
  • 数据结构之链表
    本文主要介绍链表结构,本人才疏学浅,文中如有出现知识点错误或者代码错误,还请大家多多指正。首先是单向无环链表:在单向无环链表中,每个节点由两部分组成:data和next_node,next_node用于指向下一个节点,而data表示在当前节点中存储的数据。structnode{intdata;node*next_node......
  • 重生之“我打数据结构,真的假的?”--2.单链表
    1.单链表介绍(不带头节点)1.1.链表的概念概念:链表是一种物理存储结构上非连续、非顺序的存储结构,但链表在逻辑上是连续的,顺序的,而数据元素的逻辑顺序是通过链表中的指针连接次序实现的。1.2.链表的结构typedefstructSListnode{ datatypedata; structSListnode*next;......
  • 代码随想录day27 递增子序列 | 全排列 | 全排列 II
    递增子序列递增子序列解题思路用set来去重,之后每次一个节点存入时与前一个节点进行大小比较,如果小就不存了,跳过剩余的回溯过程知识点回溯,去重心得在考虑去重的时候忘记了使用C++的数据结构set,得记下这个方法全排列全排列解题思路在回溯迭代的时候传入了一个统计数组元......