牛客网刷题-环形链表

2024-03-19 18:30
文章标签 链表 牛客 环形 网刷题

本文主要是介绍牛客网刷题-环形链表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:
想要学好嵌入式,C语言与数据结构是必要熟练掌握的,而想熟练掌握一门语言,必须经过大量的练习,刷题,至少需要一两万行的代码量,才能具有一定的编程能力,至少拿到一个功能,怎么去用编程语言去实现它,从现在开始我要开启刷题之路,提高自己的编程水平,还有最重要的面试能力。
推荐一款刷题神器

导航

  • 一.判断链表中是否有环
  • 二.链表中环的入口结点
  • 三.如何高效刷题

一.判断链表中是否有环

题目原型:
在这里插入图片描述
输入输出示例:
在这里插入图片描述
1.题目分析:题目中让我们判断一个链表是否带环,题目所说的带环不是环形链表的意思,而是最后一个结点又会重新指向前面某个结点,形成像一个环一样。

2.解题思路:
如果仅仅采用一个指针去遍历链表(某个结点能重复遍历到表示链表有环),这种方式一定得确定一个环内的结点,因为我们不知道链表在哪一个结点入环,所以这方法根本行不通。

快慢指针就能巧妙解决问题,用快慢指针去遍历链表,如果链表无环则快指针先到达终点则直接返回false,如果链表有环则快指针一定比慢指针先一步到达环内,然后快指针在环内走,直到慢指针也进入环内,此时两个指针都在环内开始走,而快指针比慢指针要快,则快指针在追上慢指针,当快指针等于慢指针,这样就说明链表内有环,但是有一点虽然我们知道因为快指针比慢指针要快所以快指针一定能追上慢指针这是毋庸置疑的,但是问题来了快指针能刚好追上慢指针嘛(快指针等于慢指针),有没有这种情况虽然快指针追上了慢指针但是每次追上都错过了(快指针每次追上的时候都跑到慢指针的前面去了),如果是这种情况的话程序就死循环了,所以说得分情况:快指针具体比慢指针快几步?

  • 1.快指针fast一次走2步,慢指针slow一次走1步
    先说结论:fast 一个能追上slow而且正好fast=slow
    证明:
    fast指针比slow指针快,fast肯定先进环,等到slow刚刚进环此时fast可能已经在环里转了几圈,也可能fast还没转到一圈。
    在这里插入图片描述
    在这里插入图片描述
    但是没关系,不管是哪种情况当fast和slow都进环的时候,fast与slow之前一定有个距离,设这个距离为N(也可能N一开始就等于0那就更好了直接fast = slow),让fast指针去追slow指针,因为fast每次比slow多走一步,则两个指针每走一次(fast走两步slow走一步),他们之间的距离就会每次都减1,减到最后N一定会被减成0(则此时fast= slow)。

在这里插入图片描述
在这里插入图片描述

  • 2.快指针fast一次走3步,慢指针slow一次走1步
    结论:不一定fast追上slow正好fast = slow
    证明:还是假设 fast和slow都进环的时候,fast与slow之间的距离为N,fast指针开始追逐slow,fast每一次比slow多走2步,则每次N都减2
    第一次:N=N-2
    第二次:N=N-4
    第三次:N=N-6

    所以当N为偶数时,N确实可以减为0(fast=slow),如果N为奇数则最后N会被减到-1,N=-1代表fast超过slow,fast等于slow的前面一个结点。如果fast超过了slow一个结点,假设环有C个结点,当N=-1时,fast 与slow 距离N又会变成C-1。如果C-1是偶数的话,则代表fast能正好追上slow(fast=slow),如果C-1是奇数的话,则fast与slow永远会错过,程序就会死循环。

所以会分成以下几种情况:

  • 当fast和slow都进环的时候,当N为偶数,fast会刚好追上slow(fast=slow)
    在这里插入图片描述
  • 当fast和slow都进环的时候,环大小为C,当N为奇数,但是C-1为偶数fast还是会刚好追上slow(fast=slow)
    在这里插入图片描述
  • 当fast和slow都进环的时候,环大小为C,当N为奇数,而且C-1也为奇数则fast与slow永远会错过,但是经过我的推理(我取一个C-1为奇数,然后逐一增加L的长度发现N的值一直是几个偶数的循环)发现好像当C-1为奇数的时候N一定为偶数,这样一来好像一次走三步fast与slow一定能刚好相遇,但是我现在无法证明,先就这样吧,有机会在去深究一下。

为什么选择fast指针走两步?
为了降低时间复杂,因为fast一次走三/四…步当slow进入环fast开始追逐slow的时候可能会错过slow。

代码实现:

bool hasCycle(struct ListNode* head ) {// write code herestruct  ListNode *slow =head,*fast=head;while(fast!=NULL && fast->next!=NULL ){slow=slow->next;fast=fast->next->next;if(fast == slow){return true;}}return false;}

在这里插入图片描述

二.链表中环的入口结点

题目原型:
在这里插入图片描述
输入输出示例:
在这里插入图片描述
1.题目分析:题目意思也清晰明了,如果链表带环就返回环的入口结点,若链表不带环,则返回空。

2.解题思路:
这题同样是用快慢指针,fast一次走2步,slow一次走1步。
假设环的大小为C,环的入口到链表起点的距离为L,fast与slow在距离入口结点X处相遇。
先说结论:一个指针从环的入口结点开始走,另外一个指针从fast与slow的相遇点(而这个指针可能会在环中转上几圈)开始走,这两个指针相遇的位置就是环的入口结点,也就是要证明L=(n-1)C+C-X

在这里插入图片描述
看完上图,解决下列3个问题这道题目迎刃而解
在这里插入图片描述
第一个问题:
在这里插入图片描述
第二个问题:
在这里插入图片描述
第三个问题:
在这里插入图片描述

代码实现:

知道思路代码就很简单了

struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {// write code herestruct  ListNode *slow =pHead,*fast=pHead;while(fast!=NULL && fast->next!=NULL){slow=slow->next;fast=fast->next->next;//找到fast与slow相遇结点if(fast == slow){struct  ListNode *meet =slow;while( pHead!= meet){pHead=pHead->next;meet=meet->next;}//返回环入口结点return meet;}}return NULL;
}

在这里插入图片描述

三.如何高效刷题

如何刷题:
1.如果你是基础不太好,可以先按照题解,跟着手打代码,重点理解题目思路,将题目所用到的知识点,解题技巧提炼出来(锻炼代码能力,解题思路)。在这里插入图片描述
2.当有一定的代码能力之后,但是看题还是没有思路,可以先看解题思路理解它,然后尝试用代码去实现它。(主要锻炼代码能力,进一步锻炼解题思维)

3.拿到一个题目自己先尝试解题,最好是能将解题思路用画图的方式体现出来,这样更能加深印象,然后用代码实现,实现之后再看看题解,或者别人的解题方法,进行对比,找到最优解题思路
在这里插入图片描述
最后:在解题过程中,碰到问题如下图(题目提交后通不过,报错(代码可能有bug),尽量独立思考,可以先尝试用它的测试用例,一步一步走读代码,看看问题出现在那个地方,如果实在是没有看出来,可以将该函数拷贝到VS中进行调试代码,一定能找出来。(锻炼自己的代码调试能力)

总结:
要想学好嵌入式C语言是根本,但是也离不开数据结构,尤其是链表、队列方面的知识,就接下来我要更新的freerots实时操作系统,就需要用到大量的链表和队列的知识,要想提高自己的编程水平,笔试能力和面试技巧,就得大量刷题手打代码

这篇关于牛客网刷题-环形链表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/826892

相关文章

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

深入手撕链表

链表 分类概念单链表增尾插头插插入 删尾删头删删除 查完整实现带头不带头 双向链表初始化增尾插头插插入 删查完整代码 数组 分类 #mermaid-svg-qKD178fTiiaYeKjl {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-

建立升序链表

题目1181:遍历链表 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2744 解决:1186 题目描述: 建立一个升序链表并遍历输出。 输入: 输入的每个案例中第一行包括1个整数:n(1<=n<=1000),接下来的一行包括n个整数。 输出: 可能有多组测试数据,对于每组数据, 将n个整数建立升序链表,之后遍历链表并输出。 样例输

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

【数据结构与算法 | 灵神题单 | 删除链表篇】力扣3217, 82, 237

总结,删除链表节点问题使用到列表,哈希表,递归比较容易超时,我觉得使用计数排序比较稳,处理起来也不是很难。 1. 力扣3217:从链表中移除在数组中的节点 1.1 题目: 给你一个整数数组 nums 和一个链表的头节点 head。从链表中移除所有存在于 nums 中的节点后,返回修改后的链表的头节点。 示例 1: 输入: nums = [1,2,3], head = [1,2,3,

c++ 链表详细介绍

链表是数据结构的一种,由节点组成,每个节点包含数据和指向下一个节点的指针。链表在C++中的实现可以是单链表、双链表或循环链表。以下是链表的详细介绍: 1. 单链表 结构: 节点(Node):每个节点包含数据和一个指针(next),指向链表中的下一个节点。 示例结构: struct Node {int data;Node* next;Node(int d) : data(d), next(

带头结点的线性链表的基本操作

持续了好久,终于有了这篇博客,链表的操作需要借助图像模型进行反复学习,这里尽可能的整理并记录下自己的思考,以备后面复习,和大家分享。需要说明的是,我们从实际应用角度出发重新定义了线性表。 一. 定义 从上一篇文章可以看到,由于链表在空间的合理利用上和插入、删除时不需要移动等优点,因此在很多场合下,它是线性表的首选存储结构。然而,它也存在某些实现的缺点,如求线性表的长度时不如顺序存储结构的