在线OJ——链表经典例题详解

news2024/12/28 21:00:05

引言:本篇博客详细讲解了关于链表的三个经典例题,分别是:环形链表(简单),环形链表Ⅱ(中等),随机链表的复制(中等)。当你能毫无压力地听懂和成功地写出代码时,那就一定可以充分的证明你的链表知识学习地非常扎实了!

更多有关C语言的知识详解可前往个人主页:计信猫

目录

一,环形链表(简单)

1,题目描述

2,思路分析

3,代码解答

 二,环形链表(简单)的拓展

1,提出问题

2,问题Ⅰ的解答

3,问题Ⅱ的解答

4,问题Ⅱ中C与N的关系

三,环形链表 Ⅱ(中等)

1,题目描述

2,思路分析

3,代码解答

四,随机链表的复制(中等)

1,题目描述

2,思路分析

3,代码解答

五,结语


一,环形链表(简单)

1,题目描述

OJ链接:环形链表

       给你一个链表,判断链表中是否存在环,若存在,则返回true,反之,则返回false

2,思路分析

        为了解出这道题,我们可以使用一个在链表中可谓是大名鼎鼎的方法——快慢指针

        所谓的快慢指针就是定义两个结构体指针slow和fast,而fast指针每次比slow指针多走一步。假如我们将fast比作兔子slow比作乌龟

        那么显而易见,假如整个链表里边没有环,则兔子(fast指针)一定会先走到NULL;假如整个链表里边有环,则兔子(fast指针)一定会先进入环,并一直在环里边循环着走,一直到乌龟(slow指针)进入环,由于兔子乌龟具有速度差,所以在某一时间刻乌龟兔子一定会相遇,所以如果兔子乌龟相遇了,即链表有环。

3,代码解答

if(head==NULL)//判断链表是否为空
        {
            return false;
        }
        struct ListNode*fast=head->next;//定义快指针
        struct ListNode*slow=head;//定义慢指针
        while(fast&&fast->next)
        {
            if(fast==slow)//两指针相遇,则成环
            {
                return true;
            }
            fast=fast->next->next;//快指针每次走两步
            slow=slow->next;//慢指针每次走一步
        }
        return false;

 二,环形链表(简单)的拓展

1,提出问题

假如你正在参加某个hr的面试,而面试官刚刚好问到你这个问题,经过充分准备的你毫不费力地将这道题秒杀了。但面试官接下来又提出了两个问题:

1,为什么fast和slow指针一定会相遇,请给出证明

2,当fast指针一次走n步时,快慢指针还会不会相遇?

这时候,阁下又该如何是好呢?

2,问题Ⅰ的解答

        其实遇到这种问题我们完全没必要慌张,我们只需要拿出作为程序员严谨的态度给予证明就可以了。

        我们可以假设在fastslow都进入环的时候,两指针的间距为N。既然每进行一次追击,fast都前进两步,slow前进一步,那么它们之间的距离一定会缩小一步

那么当我们进行了N次追击,则间距则会如此变化:N,N-1,N-2……1,0

        所以如此来看,两指针的间距一定会变为0,那么fast和slow指针也一定会相遇!(第一关通过,获得50%的offer)

3,问题Ⅱ的解答

        此时对于n的具体取值我们就需要分开讨论了,我们就先以n等于3来进行讨论吧!

我们设进入环的时候两指针的间距d等于N,故每一次追击之后d=N-(n-1)=N-2,再设整个环的长度为C

   

         当d偶数时,距离每次减少2,则可以追上。

        但当d为奇数时,就要另当别论了:

d为奇数时,第一次的追击则会错过:N,N-2,N-4……1,-1。而这里的-1意味着fast指针会跑到slow指针的前一位去,并开始新一轮的追击。

        那么此时我们就需要再次讨论d=C-1的奇偶关系了。

C奇数时,d=C-1偶数,则可以追上。
C偶数时,d=C-1奇数,则又会进入下一次追击,进入死循环,永远也追不上

         所以其他n的取值情况也就同样方法继续思考了。(第二关通过,获得100%的offer)

4,问题Ⅱ中C与N的关系

        看了上面问题Ⅱ的解析后,我们都知道了快慢指针是否可以相遇与CN的奇偶性相关。而CN之间是否有存在着奇偶性的关系呢?答案是肯定的。

我们还是以n=3来进行分析,假设进环之前的路程长度为L,当slow进入环的时候,fast已经在环里边走了x圈。

而此时slow和fast指针走的路程分别如下:

        因为n=3,那么此时fast走的路程就是slow走的路程的三倍,所以我们可以得到等式:

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

        那么进行等式化简之后,我们便可以得到:

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

        所以在问题Ⅱ中,若d=N奇数C偶数的条件一定是不存在的!!原因如下:

三,环形链表 Ⅱ(中等)

1,题目描述

OJ链接:环形链表Ⅱ

        这次的不一样的地方就是需要在普通环形链表的基础上返回链表成环的节点。

2,思路分析

        关于这道题,我将会介绍一个十分巧妙的方法:一个指针从链表的头节点head开始出发,另一个指针从fast和slow指针相遇的节点meet出发,最终它们一定会在成环的起始节点相遇

证明:

还是老样子,我们假设在fastslow相遇的时候,fast已经走了x圈。

那么此时slowfast走的路程分别为:

        所以我们便可以得到如下等式:

2(L+N)=L+x*C+N     =>    L=x*C-N

         故等号左边的L就表示第一个指针从头节点head成环起始节点的距离,等号右边的x*C不就相当于是周期吗,并没有影响,剩下的N不就表示着meet节点成环起始节点的距离吗?所以等号左右两边相等,以上方法成立!

3,代码解答

struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode*fast=head;
    struct ListNode*slow=head;
    //寻找meet节点
    while(fast&&fast->next)    
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            struct ListNode*meet=slow;//找到meet节点
            struct ListNode*cur=head;//使用cur从头节点出发
            while(meet!=cur)
            {
                cur=cur->next;
                meet=meet->next;
            }
            return meet;//cur和meet相遇的节点则为成环起始节点
        }
    }
    return NULL;
}

四,随机链表的复制(中等)

1,题目描述

OJ链接:随机链表的复制

        给定你一个链表,链表中含有一个随即指针random,它指向链表的其他节点或者NULL,如下:

         而你需要做的就是复制一个与原链表一模一样的链表,并且与对原链表毫无影响

2,思路分析

        其实这道题本身不难,复制一个链表简直易如反掌,而唯一的难点就是这个结构体成员random指针。它导致了复制random时,可能链表的那个random节点还没出现的问题。

         但是我们可以以以下方式解决问题:

        如上所示,我们可以先在每一个原链表节点之后插入一个与原节点一模一样的节点(先不管random指针),然后我们再对插入节点的random指针赋值,最后再将插入的指针取下来就可以了

        可能很多人会问道,random指针如何赋值呢?其实很简单,当我们将节点插入之后,random指针的值不就是原指针random所指向的值的next吗?这样,random的赋值就完美的解决了! 

3,代码解答

struct Node* BuyNode(int val)//设计一个创建节点的函数
{
    struct Node*newnode=(struct Node*)malloc(sizeof(struct Node));
    newnode->next=NULL;
    newnode->val=val;
    return newnode;
}
struct Node* copyRandomList(struct Node* head)
{
//防止空链表
    if(head==NULL)
    {
        return NULL;
    }
   //创建后继节点
   struct Node*cur=head;
   while(cur)
   {
        struct Node*newnode=BuyNode(cur->val);
        newnode->next=cur->next;
        cur->next=newnode;
        cur=cur->next->next;
   }
   //赋值random
   struct Node*newcur=head;
   struct Node*follow=newcur->next;
   while(follow)
   {
    if(newcur->random==NULL)//random指向NULL就特殊处理赋值NULL
    {
        follow->random=NULL;
        //指针遍历链表的移动
        newcur=newcur->next->next;
        if(follow->next)
        {
            follow=follow->next->next;
        }
        else
        {
            break;
        }
    }
    else
    {
        follow->random=newcur->random->next;
        //指针遍历链表的移动
        newcur=newcur->next->next;
        if(follow->next)
        {
            follow=follow->next->next;
        }
        else
        {
            break;
        }
    }
        
   }
   //将后继结点分离
   struct Node*phead=head->next;
   struct Node*ptail=head->next;
   while(ptail->next)
   {
        ptail->next=ptail->next->next;
        ptail=ptail->next;
   }
   return phead;
}

五,结语

        其实这些题讲起来看起来非常轻松,但也耗费了我不少时间去做出它(甚至还是在看了题解的前提下)。

        但让我值得欣慰的是,我还是结合题解做出了这些题,甚至第二题我还自己想出来自己的方法,而且我也十分顺利的在博客里清楚的讲解出了每道题的做法。这也证明了我的链表学习还是取得了效果。

        希望我的这篇博客也可以同样帮助到热爱编程学习的你,让我们一起进步一起加油!!

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

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

相关文章

面试中算法(使用栈实现队列)

使用栈来模拟一个队列,要求实现队列的两个基本操作:入队、出队。 栈的特点:先入后出,出入元素都是在同一端(栈顶)。 队列的特点:先入先出,出入元素是在两端(队头和队尾)。 分析&…

深度学习:基于Keras,使用长短期记忆神经网络模型LSTM和RMSProp优化算法进行销售预测分析

前言 系列专栏:【机器学习:项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目,每个项目都处理一组不同的问题,包括监督和无监督学习、分类、回归和聚类,而且涉及创建深度学习模型、处理非…

springboot+vue课程作业成绩可视化大屏分析系统

教师的登录功能。 教师需要可以拥有每学期新增课程的功能。 新增的课程有作业成绩,考勤成绩,考试成绩,实验成绩,其中作业成绩是平时作业1到作业8的平均成绩,最后根据占比得出学期的总评成绩。(参考我发的表…

Shell编程debug

debug调试 debug方法 sh -x显示脚本执行过程set命令设置开始debug和结束debug的位置显示脚本某一部分执行过程,解决复杂脚本故障 示例: sh -x 显示脚本执行过程 set显示脚本的部分执行过程 set -x 开始调试,从这里开始显示脚本的详细执行过…

【C++】模板初阶:泛型编程的起点

💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…

day02-分布式事务

1.分布式事务问题 1.1.本地事务 本地事务,也就是传统的单机事务。在传统数据库事务中,必须要满足四个原则: 1.2.分布式事务 分布式事务,就是指不是在单个服务或单个数据库架构下,产生的事务,例如&#xf…

鸿蒙组件样式复用简介

鸿蒙组件样式复用简介 使用Style进行复用在Component内部复用在Component外部复用使用Extend复用指定类型组件Extend支持参数传递 使用Style进行复用 在页面开发过程中,会遇到多个组件都在使用相同的样式,这时候就要考虑是不是可以将相同的样式的进行复…

Python中的`return`语句详解

Python中的return语句详解 对于初学Python或任何编程语言的人来说,理解函数如何返回值是非常重要的。在Python中,return语句用于从函数中返回结果。本篇博客将详细介绍return语句的基本用法,以及如何在不同情境中有效使用它。 什么是return…

mac安装虚拟机linux系统

需要下载的有:centos8镜像 , 虚拟器 VMware 软件包 , Termius 或者xshell 1. CentOS系统下载 linux系统一般有: CentOS、ubuntu、redhat,选择一种进行安装就可以 CentOS 2024 年开始停止维护和发布 CentOS8的下载与安装(windows下安装) 镜…

cloudreve离线下载报错Insufficient capacity

报错内容: [Warning] 2024-05-03 22:57:40 Failed to update status of download task "c0xxxxxxxxx749": Insufficient capacity 使用motrix作为离线程序,报错后,会自动暂停下载 报错原因: 初始容量只有1G&#xff0c…

算法提高之潜水员

算法提高之潜水员 核心思想&#xff1a;二维01背包 两个容量v1v2注意状态计算时j和p可以<各自的v #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 1010,M 80,K 22;int f[K][M];int k,V1,V2;int main(){ci…

中国真实婚恋相亲服务平台有哪些?分享7款专注相亲交友的脱单软件平台

终于脱单了&#xff0c;盘点一下&#xff0c;我都有用过哪些脱单App&#xff5e; 第一个&#xff0c;珍爱网&#xff0c;作为老牌相亲软件&#xff0c;拥有线上和线下门店服务&#xff0c;海量会员。优点&#xff1a;资源多&#xff0c;软件使用界面整洁干净&#xff0c;设计人…

关于 Vue.js 双向数据绑定基本实现认知

写在前面 很早的一篇博客&#xff0c;整理了部分&#xff0c;蹭假期整理完博文内容涉及:双向数据绑定 实现方式简单介绍基于发布订阅、数据劫持的双向数据绑定两种不同实现(ES5/ES6) Demo&#xff0c;以及代码简单分析Object.defineProperty && Proxy API 介绍以及特性…

Web API之BOM

BOM 一、window的常见事件1.窗口加载事件2. 调节窗口大小事件 二、定时器1.setTimeout( , )2.setInterval()3.发送短信例子4.this指向问题 三、js执行机制四、location对象1.常见属性2.例子、3.常见方法 五、navigator对象六、history对象 简介&#xff1a; BOM是浏览器对象模型…

python数据分析中数据可视化简单入门

1.折线图表 首先引入相关包pyecharts&#xff0c;如果没下载可以先下载 pip install pyecharts from pyecharts.charts import Lineline Line() # 添加x轴 line.add_xaxis([呱了个呱,羊村,牟多,蜂地,喵帕斯]) # 添加y轴 line.add_yaxis("GDP",[50,30,40,34,63,22])…

我发现不少培训班的就业辅导老师,简直是面试官的卧底——再论培训班学员的就业方式(java方向)

本人知乎账号同公众号&#xff1a;老胡聊Java&#xff0c;欢迎留言并咨询 我最近在帮一些朋友做java方面的就业辅导&#xff0c;其中有些朋友是经过培训班加持后入行java的。由于我本人做过一些大厂和外企的java技术面试官&#xff0c;我发现其中一些朋友的简历甚至根本没法通过…

基于Spring Boot的学生在线答疑系统设计与实现

基于Spring Boot的学生在线答疑系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 管理员登录界面 教师登陆界面 问题发布信息界面&am…

word中取消分页符或分段符前后的空格

在Word中&#xff0c;有时候&#xff0c;我们添加分页符后&#xff0c;从分页符后面的文字就全部掉到了下一页&#xff0c;那么如何避免呢&#xff1f; 选择word选项--高级&#xff0c;然后下滑到下面&#xff0c;将“取消分页符或分段符前后的空格”选中&#xff0c;如下图所…

Java:Map和Set

一、搜索树 在真正学习Map和Set之前&#xff0c;我们有必要先来了解一种树型结构&#xff1a;二叉搜索树&#xff01; 1、概念 二叉搜索树又被称为【二叉排序树】&#xff0c;顾名思义&#xff0c;这是一颗排好序的树&#xff01;它或者是一颗空树&#xff0c;或者是具有以下性…

未来人类文明的可持续发展

未来人类文明若要实现永远延续,建立一个演化模型确实是一个有远见的想法。演化模型可以帮助我们预测和规划未来,从而更好地应对可能出现的挑战。以下是对这个想法的展开论述: 建立演化模型:首先,我们需要收集当前节点的人类文明数据,包括科技、经济、政治、文化、环境等方…