【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点

news2025/1/13 10:28:27

目录

一、力扣第206题:反转链表

1.思路一

2.思路二

 二、力扣第876题:链表的中间结点

1.思路一

2.思路二

总结


一、力扣第206题:反转链表

题目链接:206. 反转链表 - 力扣(Leetcode)

题目描述:

 

1.思路一

对于这道题而言,我们一开始接触这种链表题可能都是懵的,但是不要慌,认真分析,一定可以做出来的。

我们就看它一开始给的测试用例来进行分析,如下图所示,他让这个链表经过一系列变化后反转了

 我们仔细观察这些区别,我们发现其实只要我们将这个指针的指向给改变了就可以了。所以我们的重点在于如何改变指针的指向

我们要改变它的指向我们应该起码给出两个指针先来记录一下要改变的两个指针

如下图所示,我们使用n1和n2来记录两个地址,其中让n1为指针,n2为链表头

 我们的第一步也很简单只需要让n2->next=n1,就可以了,但是与此同时,2所在的结点也就失去联系了,我们无法找到后面的结点,所以这种方法其实是不可行的。我们还需要第三个指针来记录后面的结点

 如下图所示,我们在改变n2的指向之前先让n3=n2->next。也就是记录了后面的一个结点

 然后接下来,我们让n1的值变为现在n2的值,让n2的值变为现在n3的值,让n3也向后走一步,这样就变成这样

 然后我们不难想到,我们继续让n2->next=n1,也就是改变了2的指向关系

然后我们继续让三个指针都往后走

 这样一来,我们继续让n2->next =n1

 然后我们继续让三个指针移动

继续改变4的指向关系

继续向后移动,并改变指向,这时候,我们发现我们已经完成了我们的目标,成功反转了这个指针

这里一定要细心,要注意我们的循环过程是,先改变指向,在向后移动,这里很多人只关心到改变了指向,却没有将指针移动。然后就会导致一些错误,指针移动后如下图

 既然我们现在反转了这个指针,那么我们现在来理清我们的思路,首先我们定义了三个指针,然后我们使用了一个循环,这个循环中先改变指针的指向,然后让三个指针依次往下走。当n2为空指针的时候,循环也就结束了

 然后我们使用了一个循环的过程. 最后我们返回n1,因为n1现在就是头节点

我们运行一下这个代码,我们发现报错了

 为什么会报错呢?其实细心的人已经发现了错误了,就是我们n3出现了空指针的解引用,如下图所示,在我们的最后,我们需要将整体指针向下移动的时候,我们这个n3已经是空指针了,那么当然最后就会出错了

 那么该如何解决呢?其实解决方案也很简单,我们这个错误只可能会出现在最后一次的循环中,让指针整体向后移动,但是此时的n3其实是什么样已经没有什么影响了,所以那不妨,当n3为NULL时候,我们就直接让n3不在继续移动即可,我们只需要对最后一部进行一下特殊处理。使用一个if语句即可

如下图所示

 当然我们还是运行一下吧,我们发现,还是出错了,但是这次不同的是,我们有两个通过了测试用例,说明我们是有一些极端情况没有考虑到才出的错误

 我们想一下,使得程序错误的输入是一开始给了一个空指针,那这样的话n3一开始的定义就出了问题了,它出现了空指针的解引用。那么特殊情况特殊处理,我们使用一个if语句来解决这个问题,因为如果这个链表使空的话,那么它反转之后还是它本身,所以我们直接返回它本身就是了

 运行结果为通过。

 在这里也给出这种方法的代码

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


struct ListNode* reverseList(struct ListNode* head){
    if(head==NULL)
    {
        return head;
    }
    else
    {
            //创建好三个指针
    struct ListNode* n1=NULL;
    struct ListNode* n2=head;
    struct ListNode* n3=head->next;
    //反转指针
    while(n2)
    {
        //反转箭头
        n2->next=n1;
        //所有指针后移
        n1=n2;
        n2=n3;
        if(n3!=NULL)
        {
            n3=n3->next;
        }
    }
    return n1;
    }
}

2.思路二

除了我们直接反转指针以外,我们其实还可以使用头插的方式来实现,我们是这样想的

对于下面这个链表而言

我们定义两个指针,cur和NewHead,一个是直接由head赋值得到,一个是指向NULL

 然后我们的想法是这样的直接让cur->next=NewHead,也就是这样子。然后上面的依次往下头插

 但是我们很快就发现问题了,那就是如果我一旦改变cur的指向,那么我们就找不到原链表了,所以我们就得一开始就定义一个指针记录下一个结点的地址

 然后,我们就让NewHead=cur;next=cur,next也继续往下走

然后我们重复这些流程

 

 

 

 上面是一次操作,我们继续

 

 

 

继续往下走

 

 

 

 

 

最后我们直接返回NewHead就可以了

代码为

 测试结果为

 

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

struct ListNode* reverseList(struct ListNode* head)
{
    //创建两个指针
    struct ListNode* cur=head;
    struct ListNode* NewHead=NULL;
    //当cur为空的时候,循环结束
    while(cur)
    {
        //记录下一个结点坐标,这样写的好处是后续不用继续对next进行特殊处理
        struct ListNode* next=cur->next;

        //头插
        cur->next=NewHead;
        //整体移动指针
        NewHead=cur;
        cur=next;
    }
    return NewHead;
}

 二、力扣第876题:链表的中间结点

 题目链接:876. 链表的中间结点 - 力扣(Leetcode)

题目描述:

1.思路一

 首先关于中间的问题,我们肯定知道是要分情况的,有奇数的情况和偶数的情况。那么这样的话,我们最容易想到的思路势必是遍历两遍链表,第一遍是得出有多少个元素,第二遍才是找到中间位置的结点。这种方法很简单,但是时间就慢了很多。

2.思路二

还有一种思路也是十分常用的,那就是快慢指针。我们定义两个指针。一个一次走一步,一个一次走两步,这样我们最后也能找出这个中间结点。我们来画图理解一下

我们先看奇数链表的情况

 我们让slow走一步,fast走两步

继续往下走

 我们可以看出来,当fast->next==NULL时候,快慢指针就找到了中间结点也就是slow

那我们在来看看偶数的情况

 

 

我们可以看出来当fast==NULL时,我们就找到了中间结点(注意我们题目的要求是,如果有两个中间结点,返回第二个结点的值)

 所以我们就可以得出代码了

 而运行结果当然是可以通过的

 代码为

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


struct ListNode* middleNode(struct ListNode* head){
    //定义快慢指针
    struct ListNode* slow=head,*fast=head;
    //开始循环走,当fast和fast->next都不为空的时候,就可以接着往下走
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    //返回slow即可
    return slow;
}


总结

本小节讲解了两个经典的力扣题,希望大家都能够学会

如果对你有帮助,记得一键三连哦!!!

想看更多精彩的讲解,那么一定要关注我哦!!!

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

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

相关文章

gitee学习笔记(使用命令行上传、拉取资料)

1、创建一个仓库(比如命名为firstgit) 2、在文件夹中准备好要上传的资料 3、单击鼠标右键,打开Git Bash Here 进行命令行操作(当然,前提是需要安装git客户端,可去官网安装) 4、上传文件 ①git init //文件初始…

【mybatis-plus】自定义多数据源,动态切换数据源事务失效问题

背景 做了一个和navicat一样的工具,web版工具,然后数据库链接信息都是存在一个主数据库表的里,所以这里涉及到了动态切换数据源,以及一些事务等。今天说下多数据源切换时,事务失效。 目录 一、常见的事务失效 Transac…

大数据必学Java基础(一百一十二):开发案例之登录验证

文章目录 开发案例之登录验证 一、准备实体类 二、准备一些页面和静态资源

Spring boot day1

Maven 进阶 spring boot 框架 spring boot 相比于SSM框架的优缺点 优点: 创建独立的sping应用程序内嵌的tomcat,无需部署war文件简化的maven配置自动配置spring提供生产就绪型功能,如指标,健康检查和外部配置 特性:…

3.1 卷积神经网络基础

文章目录计算机视觉的发展历程卷积神经网络卷积(Convolution)卷积计算填充(padding)步幅(stride)感受野(Receptive Field)多输入通道、多输出通道和批量操作飞桨卷积API介绍卷积算子…

碰焊机触摸屏软件开发

1 软件需求 人机界面为MCGS 10寸触摸屏1062KW,接口为RS232/RS484/以太网,供电电源为24V。机触摸屏的功能为机器人的基本状态信息显示和对机器人的控制及参数给定。 目前设计的小车分成两栏共10格,需要将对应的触摸屏大致分成相应的10大格&a…

【嵌入式】AI落地部署技能

针对不同平台对生成的模型进行转换,也就是俗称的parse、convert,即前端解释器针对转化后的模型进行优化在特定的平台(嵌入端或者服务端)成功运行已经转化好的模型在模型可以运行的基础上,保证模型的速度、精度和稳定性用C、cuda写算子(预处理…

AWS-Eventbridge-事件总线实践

aws eventbridge 功能主要使用场景为,针对账号发生各种事件,发生告警,可以发送sns告警,也可以配置发送到当前区域或者其他账号当前区域的事件总线上汇总,再做下一步规划eventbridge 事件总线类似与整个事件的一个目录集…

机器学习——03决策树算法

机器学习——03决策树算法 参考资料 AIlearningMachine-Learning-in-Action庞善民.西安交通大学机器学习导论2022春PPT 具体算法的原理步骤请参考本人的另一篇博文:[机器学习导论]—— 第四课——决策树 一、信息熵与信息增益 🔥信息熵 信息熵使信息…

中小企业OA系统的设计与实现

开发工具(eclipse/idea/vscode等): 数据库(sqlite/mysql/sqlserver等): 功能模块(请用文字描述,至少200字): 模块划分:通知类型模块、通知信息模块、部门模块、员工模块、考勤模块、工资模块、奖惩类型、奖惩信息、请假…

USACO开赛!这份参赛指引必看!

美国信息学奥赛USACO 2022 – 2023赛季首场比赛于明日(12月16日)开始!这份参赛指引,一定要认真看噢~ 第一步:打开 USACO 官网:http://www.usaco.org/,点击【注册新账号】,开始注册账…

宽凳科技完成超亿元B1轮融资 率先突破高精地图量产落地

近日,国内领先的高精地图及其智能应用综合解决方案服务商宽凳科技宣布完成B1轮超亿元融资。本轮融资由聚焦于新能源汽车产业链投资及新兴技术产业投资的紫峰资本与信益资本联合领投,崇业投资跟投,同时本轮资本引入了德清政府战略投资&#xf…

WebDAV之葫芦儿·派盘+Xplore

Xplore 支持WebDAV方式连接葫芦儿派盘。 手机文件太多、太乱,本地目录中找不想要的文件,怎么办?推荐使用Xplore将手机中的文件以不同的文件方式罗列出来,并展示给用户。文件管理器以图片、音乐、视频、文档、压缩包及安装包等类型进行分类,使手机中的文件一目了然的分列…

离线地图开发包

相关教程: 1、如何搭建离线地图开发环境 视频教程 2、下载离线地图数据(金字塔瓦片数据) 视频教程 3、下载离线地图地形数据库(实现地表高低起伏) 4、添加离线地图数据到本地服务器 (含3D) 视频…

【身份证识别】BP神经网络身份证号码识别【含Matlab源码 1344期】

⛄一、身份证号码识别简介(附课题作业报告) 1 引言 当今是一个信息高度发达的时代,对于每个公民而言身份证那一连串的数字体现了个人信息的唯一性,出于保障公民合法权益和社会治安的考虑,越来越多的行业都开始建立自己…

数据价值深度挖掘,分析服务上线“探索”能力

近日,华为分析服务6.9.0版本发布,正式上线探索能力。开发者可自由定义与配置分析模型,支持报告实时预览,数据洞察体验更加灵活与便捷。 新上线的探索能力中,有漏斗分析、事件归因、会话路径分析三个高级分析模型。在原…

45-Jenkins-Sidebar Link插件实现添加侧边栏

Sidebar Link插件实现添加侧边栏前言安装插件使用插件自由风格项目使用Pipeline项目使用前言 本篇来学习下使用Sidebar Link插件在项目侧边栏添加自定义功能按钮链接 安装插件 Manage Jenkins --> Mangage Plugins --> 可选插件 --> 输出框输入 Sidebar Links 使…

【猿如意】中的『Bluefish』工具详情介绍

目录 一、工具名称 二、下载安装渠道 2.1 什么是猿如意? 2.2 如何下载猿如意? 2.3 如何在猿如意中下载开发工具? 三、Bluefish工具功能简介 四、Bluefish的下载和安装 4.1下载Bluefish 4.2安装Bluefish 五、Bluefish的基本使用 5.1…

Linux学习02-主机管理与磁盘分区

1 Linux与硬件的搭配 实际上,在Linux服务器中,内存的重要性比CPU重要。因为内存不够就会使用到硬盘的内存交换分区。 显卡对于不需要X-Windows的服务器来哦说,是最不重要的一个组件。 各设备在Linux中的文件命名。 在Linux系统中&#xf…

Linux常用调试工具

编译阶段 Linux入门 nm 获取二进制文件包含的符号信息 strings 获取二进制文件包含的字符串常量 strip 去除二进制文件包含的符号 readelf 显示目标文件详细信息 objdump 尽可能反汇编出源代码 addr2line 根据地址查找代码行 运行阶段 gdb 强大的调试工具 ldd 显示程序需…