【刷题篇】链表(下)

这篇具有很好参考价值的文章主要介绍了【刷题篇】链表(下)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档
  1. 前言🌸

各位读者们好,本期我们来填填之前留下的坑,继续来讲解几道和链表相关的OJ题。但和上期单向链表不一样的是,我们今天的题目主要是于环形链表有关,下面让我们一起看看吧。

💻本期的题目有: 环形链表环形链表II求环形链表环长
  1. 环形链表💍

a.题目

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

b.题解分析

第一种方法,我们可以遍历链表,使用哈希表来保存已经经过的结点。每次经过一个结点时,通过哈希表判断结点是否被访问过,如果有,则说明存在环;如果没有则继续访问下一结点,以此循环直到遍历完整个链表。这样的时间复杂度为O(N),空间复杂度为O(N),不满足题目的进阶解法

第二种方法,我们可以使用上期学习的快慢指针法定义步长为2的快指针和步长为1的慢指针遍历链表。我们假设链表如果存在环,则快慢指针在某一时刻一定会在环内相遇;而如果不存在环,由于快指针速度比慢指针快,因此它们永远无法相遇。动态效果如下:

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档
我们可以看到如果链表存在环时, 当慢指针进入环中后,快指针就会开始绕环追逐慢指针。我们假设此时快慢指针距离为n,由于 v(快)-v(慢)=1,则每次行动快慢指针的距离就会缩短1, 行动n次后快慢指针一定就会相遇。因此我们可以通过判断是否相遇来判断是否有环。

c.AC代码

struct ListNode
{
    int val;
    struct ListNode* next;    
};
bool hasCycle(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)
        {
            return true; //相遇
        }
    }
    return false; //没有相遇、没有结点、只有一个结点且非循环,不存在环

}

d.拓展思考

通过以上例子,我们知道 速度差为1快慢指针可以用来判断链表是否存在环。那么, 速度差为2的是不是也可以用来判断呢?速度差为3的呢?为n的呢?

我们来分析一下:当快慢指针的速度差为2时,假设慢指针进入环时快指针与其距离为n,环的总长为m,如下:

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

由于它们的速度差为2,则每次行动后n=n-2。我们很容易发现,如果n为偶数时,当行动计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档次后快慢指针就会相遇;但是当n为奇数时,最后快慢指针就会错过,进入下一轮追赶中。而在第二轮追赶开始时,快慢指针距离为m-1,假如m-1又是奇数,则本轮又会错过进而进入第三轮追逐。然后第三轮开始时依旧相距m-1,又会错过,以此反复......,最后永远不会相遇(史上最遥远的距离,无非就是我在你身旁,你却不理不睬😭)因此,使用速度差为2的快慢指针,不能保证是否可以判断出某个链表是否存在环,速度差为3,为n的同理

  1. 环形链表 II✈

a.题目

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

b.题解分析

我们同样可以在上一题的基础上使用快慢指针来求解。

我们假设链表头到环入口的长度为S,环的长度为C。当慢指针走到环入口,此时快指针的位置和慢指针的位置关系如下:

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

我们假设此时快慢指针的距离为L,这里可能有读者有疑问:快指针是慢指针速度的2倍,那L的大小不应该是S吗?实际上,当slow到达环入口时,fast可能已经绕环n圈了,所以fast实际走过的长度共为S+nC+L(计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档)。由此我们可以得出S+nC+L=2S,即L=S-nC在这之后,快指针开始追逐慢指针,我们假设在如下位置相遇:

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

假设共进行了D次追逐才追上了慢指针,由快指针比慢指针快一倍可以得出以下关系:

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

因此,相遇点到快指针最初位置的距离为S-nC-D,由此可以得出相遇点到环结点的距离为S-nC-D+D=S-nC,如下:

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档
计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

至此,我们发现链表头到环入口的距离S与相遇点到环入口的距离S-nC相差n个环的长度

由此我们算法的思路是:

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

c.AC代码

struct ListNode {
    int val;
    struct ListNode* next;
};
struct ListNode* detectCycle(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) //相遇,存在环
        {
            //两个指针找环入口
            slow = head;
            while (slow!=fast)
            {
                slow = slow->next;
                fast = fast->next;
            }
            return slow;
        }
    }
    return NULL;//没有相遇、没有结点、只有一个结点且非循环,不存在环,返回空

}    
  1. 求环形链表的环长💫

a.题目

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

b.题解分析

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

计算链表的环的长度,C语言刷题打卡,链表,数据结构,学习,c语言,算法,Powered by 金山文档

c.AC代码

 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;

}

以上,就是本期的全部内容啦🌸

制作不易,能否点个赞再走呢🙏文章来源地址https://www.toymoban.com/news/detail-822653.html

到了这里,关于【刷题篇】链表(下)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言编程之旅 6】刷题篇-for循环

    思路: 两个循环进行控制 外层循环控制打印多少行 内部循环控制每行打印多少个表达式以及表达式内容, 比较简单,具体参考代码 思路: 采用循环的方式输入一个数组 使用max标记数组中的最大值,采用循环的方式依次获取数组中的每个元素,与max进行比较,如果arr[i]大于

    2024年01月21日
    浏览(37)
  • C语言编程入门之刷题篇(C语言130题)(8)

    (题目标题可以直接跳转此题链接) BC72 平均身高   从键盘输入5个人的身高(米),求他们的平均身高(米)。 输入描述: 一行,连续输入5个身高(范围0.00~2.00),用空格分隔。 输出描述: 一行,输出平均身高,保留两位小数。 输入:1.68 1.75 1.82 1.60 1.92 输出:1.75  参考

    2024年02月02日
    浏览(28)
  • 数据结构:图文详解双向链表的各种操作(头插法,尾插法,任意位置插入,查询节点,删除节点,求链表的长度... ...)

    目录 一.双向链表的概念 二.双向链表的数据结构 三.双向链表的实现 节点的插入 头插法 尾插法 任意位置插入 节点的删除 删除链表中第一次出现的目标节点 删除链表中所有与相同的节点 节点的查找 链表的清空 链表的长度 四.模拟实现链表的完整代码 前言: 在上一

    2024年02月05日
    浏览(34)
  • 数据结构:图文详解单链表的各种操作(头插法,尾插法,任意位置插入,删除节点,查询节点,求链表的长度,清空链表)

    目录  一.什么是链表 二.链表的实现 节点的插入 头插法 尾插法 指定位置插入 节点的删除 删除第一次出现的节点 删除所有节点 节点的查找 链表的清空 链表的长度 前言: 在上一篇文章中,我们认识了线性数据结构中的顺序表,而本篇文章则是介绍线性数据结

    2024年02月05日
    浏览(33)
  • 【Leetcode刷题】链表的中间结点和合并两个有序链表

    生命如同寓言,其价值不在与长短,而在与内容。                                ——塞涅卡 目录 一.链表的中间结点 1.快慢指针 二.合并两个有序链表  1.尾插法 给你单链表的头结点 head ,请你找出并返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点

    2023年04月17日
    浏览(31)
  • 算法刷题-链表-删除链表的倒数第N个节点

    力扣题目链接 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 进阶:你能尝试使用一趟扫描实现吗? 示例 1: 输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5] 示例 2: 输入:head = [1], n = 1 输出:[] 示例 3: 输入:head = [1,2], n = 1 输出:[1] 双指针的经典应用,

    2024年02月08日
    浏览(29)
  • 反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】

    给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 这里解释一下三个指针的作用: n1:记录上一个节点,如果是第一个就指向空 n2:记录此节点的位置 n3:记录下一个节点的位置,让翻转后能找到下一个节点

    2024年02月03日
    浏览(38)
  • Leetcodes刷题之删除链表的倒数N个结点和删除链表的中间的结点

    吾心信其可行,则移山填海之难,终有成功之日。                           --孙中山 目录 🍉一.删除链表的倒数N个结点 🌻1.双指针 🍁2.求链表的长度 🌸二.删除链表的中间的结点 给你一个链表,删除链表的倒数第  n   个结点,并且返回链表的头结点。 示例 1: 示例

    2024年02月01日
    浏览(32)
  • 【LeetCode刷题日志】138.随机链表的复制

    🎈个人主页:库库的里昂  🎐C/C++领域新星创作者  🎉欢迎 👍点赞✍评论⭐收藏 ✨收录专栏:LeetCode 刷题日志 🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗 目录 1.题目描述 2.解题思路+代码实现 方法:迭代 + 节点拆分 思

    2024年02月04日
    浏览(30)
  • 【刷题专栏—突破思维】LeetCode 138. 随机链表的复制

    前言 随机链表的复制涉及到复制一个链表,该链表不仅包含普通的next指针,还包含random指针,该指针指向链表中的任意节点或空节点。 题目链接: LeetCode 138. 随机链表的复制 题目介绍: 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指

    2024年02月05日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包