[链表]求中间节点、反转链表、回文链表

一、求链表的中间节点

876. 链表的中间结点 - 力扣(LeetCode)

快慢指针法:

        分别定义两个节点的指针(pSlow和pFast)指向链表的第一个节点,然后两个指针一起往后遍历链表,pFast一次移动两个节点,pSlow一次移动一个节点,通过路程差可知,当pFast遍历完链表时,pSlow只遍历了一半的节点数,此时pSlow指向的节点就是我们要找的中间节点。

链表节点数为奇数和偶数时的情况:

        

 具体代码:

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        //快慢指针法
        ListNode* pFast = head;
        ListNode* pSlow = head;

        //注意先判断pFast所指的节点是否为空再判断其next指针是否为空,否则会出现解引用空指针的情况
        while(pFast != nullptr && pFast->next != nullptr)
        {
            pFast = pFast->next->next;//移动两步
            pSlow = pSlow->next;//移动一步
        }
        
        return pSlow;
    }
};

 二、反转链表

206. 反转链表 - 力扣(LeetCode)

        定义三个指针(pPrev,pCur,pNext),分别指向前一个节点,当前节点,和后一个节点,我们的pPrev和pNext一开始指向空,因为一开始pCur是反转后的尾结点,而头结点有可能为空指针,一开始令pNext = pCur->next会有解引用空指针的风险。每次遍历将当前节点的下一个节点指针改为指向前一个节点指针pPrev,然后更新三个指针的指向,往后移动一步。在更新指针时,因为pCur->next的指向已经改变,要往后遍历就需要保存之前pCur->next所指向的节点,所以我们需要在每次修改pCur->next的指向时先用pNext保存pCur->next的节点地址,当修改好指向后,就可以找到原来pCur的下一个节点了。重复操作直到pCur遍历完整个链表就完成了链表的反转。

下面是示例图:

具体代码: 

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pPrev = nullptr;
        ListNode* pCur = head;
        ListNode* pNext = nullptr;

        while(pCur != nullptr)
        {
            //保存pCur后面的节点
            pNext = pCur->next;
            //将pCur连接上一个节点
            pCur->next = pPrev;
            //更新指针指向
            pPrev = pCur;
            pCur = pNext; 
        }

        //此时pPrev就是头结点,pCur指向空
        return pPrev;
    }
};

三、判断回文链表

        LCR 027. 回文链表 - 力扣(LeetCode)

        由于单链表不能逆向遍历,判断回文结构时有点麻烦,可以使用暴力算法来解决这个题目,但是,面试题对这道题有严格要求,需要设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

        这个时候需要使用我们之前写的求链表的中间节点和反转链表的算法来完成时间复杂度为O(n),额外空间复杂度为O(1)的要求了。具体思路就是先找到这个链表的中间节点,将中间节点后面的子链表视为一个新的链表,将其反转,然后将反转后的结果和前一半的子链表进行对比,看每一个节点是否都相同,否则就不是回文链表。在我们依次比较完后,我们还需要将反转的子链再反转回去,恢复链表原来的结构,防止内存泄漏,因为在函数外头只有第一个子链的头结点,而第二个子链的头结点是找不到的,就会导致第二个子链的节点内存泄漏,并且破坏了链表的原有结构

将链表拆分成两个子链表:

奇数个:

偶数个:

        然后就比较两个链表是否相同就可以了。

具体代码:

class Solution {
public:
    //快慢指针求中间节点
    ListNode* middleNode(ListNode* head) 
    {
        //快慢指针法
        ListNode* pFast = head;
        ListNode* pSlow = head;

        //注意先判断pFast所指的节点是否为空再判断其next指针是否为空,否则会出现解引用空指针的情况
        while(pFast != nullptr && pFast->next != nullptr)
        {
        pFast = pFast->next->next;//移动两步
        pSlow = pSlow->next;//移动一步
        }

        return pSlow;
    }

    ListNode* reverseList(ListNode* head)
    {
        ListNode* pPrev = nullptr;
        ListNode* pCur = head;
        ListNode* pNext = nullptr;

        while(pCur != nullptr)
        {
            //保存pCur后面的节点
            pNext = pCur->next;
            //将pCur连接上一个节点
            pCur->next = pPrev;
            //更新指针指向
            pPrev = pCur;
            pCur = pNext; 
        }

        //此时pPrev就是头结点,pCur指向空
        return pPrev;
    }
    bool isPalindrome(ListNode* head) 
    {
        //找到中间节点
        ListNode* pMid = middleNode(head);
        
        
        //逆转中间节点后的链表
        ListNode* reHead = reverseList(pMid);

        //遍历判断两个链表是否相等
        ListNode* pList1 = head;
        ListNode* pList2 = reHead;

        while(pList1 != nullptr && pList2 != nullptr)
        {
            if(pList1->val != pList2 ->val)
                return false;
            
            pList1 = pList1->next;
            pList2 = pList2->next;
        }

        //将两个链表恢复原状,防止内存泄露
        reverseList(reHead);
        return true;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Java的高校学生勤工助学优派系统的设计与实现(论文+源码)_kaic

摘 要 高校勤工助学管理系统的出现,让学生的工作更加标准,不仅仅使高校办公室的办公水平以及管理水平大大提高,还优化了勤工助学资金的使用方式方法,完善了资助所需费用的资源配置,可以卓有成效地缩减学校的管理经费。本系统主…

EPSON RX8111CE+松下高性能电池的组合应用

RTC是一种实时时钟,用于记录和跟踪时间,具有独立供电和时钟功能。在某些应用场景中,为了保证RTC在断电或者其他异常情况下依然能够正常工作,需要备份电池方案来提供稳定的供电。本文将介绍EPSON爱普生nA级RTC RX8111CE松下Panason…

Android 生成正式版密钥库 KeyStore

步骤1:打开生成正式版密钥库设置 点击 Build 菜单,选择 Generate Signed App Bundle or APK: 这是打开后的样子: 步骤2:选择 APK Android App Bundle 是用于上架 Google Play 商店的。 正常情况下选择 APK。 选择…

JVM学习-javap解析Class文件

解析字节码的作用 通过反编译生成字节码文件,可以深入了解Java工作机制,但自己分析类文件结构太麻烦,除了第三方的jclasslib工具外,官方提供了javapjavap是jdk自带的反解析工具,它的作用是根据class字节码文件&#x…

C语言实现Hash Map(3):Map代码优化

在上一节中,我们学习了C语言实现Hash Map(2):Map代码实现详解,通过代码,我们更深入地了解了Map实现的原理,学习了如何通过key找到对应的桶并加入节点。也正如上一节提到的,虽然这是github中star比较多的代码…

You don‘t have enough free space或者no space left on device异常

1.磁盘空间不足 Linux安装软件显示 You dont have enough free space 或者docker拉镜像时,出现磁盘空间不足的情况 no space left on device 如果你是ubuntu系统。查看磁盘空间 df -h 多半是这个目录满了/dev/mapper/ubuntu--vg-ubuntu--lv 大多情况我们只希望扩…

Android 14 - 绘制体系 - VSync(1)

整体框架 VsyncConfiguration:一些基本参数的配置类,比如PhaseOffsets、WorkDuration等。 Scheduler:作为SF生成和派发VSync的整体调度器,主要面向SurfaceFlinger提供VSync相关接口。Scheduler包含对所有屏幕的VSync的控制。本身是…

影响所有股票、债券和ETF交易!一文看懂美国“T+1”结算新规

T1对投资者有何好处?有哪些风险?T1已经到来,T0还远吗? 美股将在本周迎来历史性时刻。 从当地时间5月28日开始,美股交易结算周期将由T2缩短至T1,即投资者当天卖出的股票,在交易后一个工作日就能…

[Python]pyenv 环境配置

。pip install pyenv安装 / 去Git 下载pyenv版本安装 。安装好后控制台输入pyenv查看版本 。pyenv install --list列出所有pyenv可以支持的python版本 。pyenv install 3.9.7 安装指定的版本 。在pycharm里,可以选中项目,点击File-Settings&#xff0…

如何评价 OpenAI 最新发布支持实时语音对话的模型GPT-4o?OpenAI发完GTP-4o,国内大模型行业还有哪些机会?

文章目录 OpenAI发完GTP-4o,国内大模型行业还有哪些机会?详细了解一下OpenAI最新发布的支持实时语音对话的模型GPT-4o国内大模型如何寻找发展机会?想要发展技术必须要创新与追赶或许应用场景拓展也是一种出路产业生态构建 ChatGPT 问世才 17 …

大字体学生出勤记录系统网页源码

源码介绍 上课需要一个个点名记录出勤情况,就借助AI制作了一个网页版学生出勤记录系统, 大字体显示学生姓名和照片,让坐在最后排学生也能看清楚,显示姓名同时会语音播报姓名, 操作很简单,先导入学生姓名…

制作ARM架构 docker镜像

docker简介 docker客户端 Docker 客户端有两种替代选项:名为 docker 的命令行应用程序或名为 Docker Desktop 的基于图形用户界面 (GUI) 的应用程序。 CLI 和 Docker Desktop 均与 Docker 服务器交互。 来自 CLI 或 Docker Desktop 的 docker 命令使用 Docker REST API 将指…

C++ | Leetcode C++题解之第116题填充每个节点的下一个右侧节点指针

题目: 题解: class Solution { public:Node* connect(Node* root) {if (root nullptr) {return root;}// 从根节点开始Node* leftmost root;while (leftmost->left ! nullptr) {// 遍历这一层节点组织成的链表,为下一层的节点更新 next…

Android LAME原生音频

前言 我想大家都做过录音的功能吧,首先想到的是不是MediaRecorder?今天我们不用MediaRecorder,而是使用LAME库自己编译音频编码模块,很明显,这个需要用到NDK。凡是涉及到音视频编解码这块的,都需要用到And…

STM32H750外设之ADC通道选择

目录 概述 1 通道选择功能介绍 2 通道选择( SQRx、 JSQRx) 2.1 通道复用 2.1.1 通道介绍 2.1.2 通道框图 2.2 转换分组 2.3 内部专用通道 3 通道预选寄存器 (ADCx_PCSEL) 3.1 功能介绍 3.2 预选通道寄存器 概述 本位主要介绍STM32H750外设之…

2024年03月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,共50分) 第1题 在Python中,hex(2023)的功能是?( ) A:将十进制数2023转化成十六进制数 B:将十进制数2023转化成八进制数 C:将十六进制数2023转化成十进制数 D:将八进制数2023转化成十进制数 答案:A …

迭代器模式(行为型)

目录 一、前言 二、迭代器模式 三、总结 一、前言 迭代器模式(Iterator Pattern)是一种行为型设计模式,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。总的来说就是分离了集合对象的遍历行为,抽象出…

深度学习环境安装教程-anaconda-python-pytorch

首先是anaconda的安装,可以从下面地址下载安装包 Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 尽量选择最新的日期的anaconda进行安装,我这里是windows电脑,因此选择了windos-x86_64.exe&#xf…

TIM(Timer)简介

TIM(Timer)定时器介绍 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时不仅具备基本的定时中断功能,而且…

软件测试金字塔,对号入座,你在哪层?

自从学习了软件测试,脑袋也清晰了,目标也明确了,就是不知道学到哪里了.中间有很多的困难也有很多成就感,你目前在那个阶段呢? 初级测试工程师 技能要求:需求分析,使用等价类边界值等方法进行用例设计,执行功能测试,发现提交跟踪bug,使用禅道,会在测试中会操作数据库进行检查和…