LeetCode单链表OJ题目做题思路分享

news2025/1/10 11:45:26

目录

    • 移除链表元素
    • 链表的中间节点
    • 链表中倒数第K个节点
    • 合并两个有序链表

移除链表元素

链接: link
题目描述:
在这里插入图片描述
思路分享

我们上个博客分享了第一种方法,下面我们分析第二种方法:思路就是将每一个不等于我们要删除的值的节点依次尾插。
我们要记录我们尾插之后的新的头,以便于我们将新链表的头返回。
尾插的情况有以下两种:
如果当前要插入的值不是我们要删除的值时,我们要判断以下两种情况
1.链表没有元素,是空链表,这时就需要我们将链表新的头赋值为当前节点的值,并且此时的尾也指向链表新的头。newhead=tail=cur。
2.链表当中没有元素,不是空链表时,将此节点直接插入到当前链表的尾部。tail->next = cur,tail = tail ->next
如果当前要插入的值是我们要删除的值时:
新定义一个节点用来保存我们要删除的节点,将cur指针指向下一个节点,再free掉我们定义的节点。struct ListNode* del = cur;cur = cur->next ;free(del);
这里要注意两个点:
1.每次进行插入操作之后,cur指针都要向下移动
2.为了避免出现野指针问题,每次进行插入结束后,尾指针的next域都要置空。

这里出现一个问题,cur指针向下移动和tail的next域置空的顺序:
在这里插入图片描述
为什么第一个是正确的呢?
解答:
下图步骤意思是:让newhead和tail指针指向节点1
在这里插入图片描述
此时cur指向1节点,cur的next依旧指向的是节点2,这一点并没有改变,所以cur=cur->next指向的是节点2。
但是如果先将tail->next置空,那么cur->next也是空,因为此时cur和tail指向的是同一个节点的,所以此时cur->next也是NULL,会导致cur=cur->next时候找不到下一个节点,所以我们的顺序必须是先cur=cur->next,再将tail->next置空。
代码实现:

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* cur = head;
    struct ListNode* newhead = NULL;
    struct ListNode* tail = NULL;
    while (cur)
    {
        if (cur->val != val)//和删除的值不相等
        {
            if (tail == NULL)//第一次插入
            {
                newhead = tail = cur;
            }
            else
            {
                tail->next = cur;
                tail = tail->next;
            }
            tail->next = NULL;
            cur = cur->next;

        }
        else//和删除的值相等
        {
            struct ListNode* del = cur;
            cur = cur->next;
            free(del);
        }
    }
    return newhead;
}

链表的中间节点

链接: link
题目描述:
在这里插入图片描述
题目思路:

快慢指针slow和fast
slow指针一次走一步,fast指针一次走两步。快指针速度是慢指针二倍,当快指针走到终点时,慢指针正好指向中间节点。
这里存在两种情况:刚好这两种情况可以作为我们循环的判断条件。
1.fast->next=NULL
在这里插入图片描述
2.fast=NULL
在这里插入图片描述

代码实现:

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while(fast&&fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

链表中倒数第K个节点

链接: link
题目描述:
在这里插入图片描述
题目思路:

本题我们的思路依然是一个快慢指针的问题
在这里插入图片描述

fast走到最后一个元素时,slow和fast同时向下一个节点移动,直到fast指向的位置为空,slow指向的位置就是我们要返回的元素。
本题我们要找倒数第1个节点,那么就以第一个节点为例,当slow和fast指针拉开1个举例时,两个指针同时向下移动,直到下面情况,slow指向的就是我们要找的值。
在这里插入图片描述
注意两点问题
1.如果链表的长度小于k的时候,也会造成fast空指针问题,所以在fast指针走k次的循环过程中,要保证不是因为单链表长度小于k而造成的空指针问题。
2.同时也要判断传过来的pListHead不为空或者k的值是否小于等于0,只要二者有一个满足,就要返回NULL。

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k)
{
    if (!pListHead || k <= 0)//保证传过来的头不是空并且k的值是有效值
    {
        return NULL;
    }
    //开始两个指针同时指向链表的头
    struct ListNode* slow = pListHead;
    struct ListNode* fast = pListHead;
    while (k--)
    {
        if (fast)
        {
            fast = fast->next;
        }
        else
        {
            return NULL;//单链表长度小于K会造成fast空指针
        }
    }
    while (fast)
    {
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}

合并两个有序链表

链接: link
题目描述:
在这里插入图片描述
在这里插入图片描述
题目思路:

两个指针同时指向List1和List2两链表头部。开始进行链接:
本题需要5个指针,List1,List2,tail,newhead
1、如果List1的值比List2的值小,那么List1的头就是我们合并后链表新的头,newhead = List1,之后让List1指向下一个节点,并且tail指向刚刚被插入的节点。
与此同时如果List2的值比List1的值小,那么List2的头就是我们合并后链表新的头,newhead = List2,之后让List2指向下一个节点,并且tail指向刚刚被插入的节点。
2、有了新链表的头之后,剩下的步骤就是比较两个节点的大小,那个节点值大,就将哪个节点拿下来尾插,并且让尾指针tail指向该尾插的节点。
3、在进行不断的尾插的过程中肯定会有一条链表为空,如果是List1为空,那么直接让tail->next链接List2,否则链接List1。
注意:
我们还要注意一点就是,很有可能给我们的两条链表有一条是空链表,此时只需要返回那条不为空的链表就好。

代码实现:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if(list1==NULL)
    {
        return list2;
    }
    if(list2==NULL)
    {
        return list1;
    }
    if(list1==NULL&&list2==NULL)
    {
        return NULL;
    }
    struct ListNode* newhead = NULL;
    struct ListNode* tail = NULL;
    while(list1&&list2)
    {
        if(list1->val<list2->val)
        {
            if(newhead ==NULL)
            {
                newhead = tail = list1;
            }
            else
            {
                tail->next = list1;
                tail = tail->next;
            }
            list1 = list1->next;
        }
        else
        {
             if(newhead ==NULL)
            {
                newhead = tail = list2;
            }
            else
            {
                tail->next = list2;
                tail = tail->next;
            }
            list2 = list2->next;
        }
    }
    if(list1)
    {
        tail->next = list1;
    }
    if(list2)
    {
        tail->next = list2;
    }
    return newhead;
}

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

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

相关文章

【硬件】嵌入式电子设计基础之产品实践

电子技术是一门实践性非常强的学科&#xff0c;学习电子元器件基础知识和设计技能&#xff0c;最终为的是把具备一定功能的电路板制作出来&#xff0c;解决科研、生产、生活中的实际问题。 本篇文章从实际的电子产品出发&#xff0c;让您能够初步体验电子产品的硬件设计过程&am…

【Unity编辑器】拓展Project视图

目录 1、拓展右键菜单 2、创建一个菜单 3、拓展布局 4、监听事件 首先创建一个Editor文件夹&#xff0c;此文件夹可以作为多个目录的子文件夹存在&#xff0c;这样开发者就可以按照功能来划分&#xff0c;将不同功能的编辑代码放在不同的Editor目录下。 如果属于编辑模式下…

多维时序 | MATLAB实现BP、SVM、LSSVM多变量时间序列预测(考虑历史特征的影响,多指标、多图输出)

多维时序 | MATLAB实现BP、SVM、LSSVM多变量时间序列负荷预测(考虑历史特征的影响&#xff0c;多指标、多图输出) 目录 多维时序 | MATLAB实现BP、SVM、LSSVM多变量时间序列负荷预测(考虑历史特征的影响&#xff0c;多指标、多图输出)预测效果基本介绍程序设计学习总结参考资料…

大规模并行处理架构Doris概述篇

目录 1 Doris概述篇1.1 前言1.2 Doris简介1.3 核心特性1.4 Doris特点1.5 Doris发展历程1.6 对比其他的数据分析框架1.7 开源OLAP引擎对比1.8 使用场景1.9 使用用户 2 Doris原理篇2.1 名称解释2.2 整体架构2.3 元数据结构2.4 数据分发 1 Doris概述篇 1.1 前言 Doris由百度大数据…

BI 商业智能和报表,傻傻分不清楚?一文给你讲透

我们经常所听到的大数据、商业智能BI、数据分析、数据挖掘等我们都统称为数据信息化。数据信息化可以帮助企业全面的了解企业的经营管理&#xff0c;从经验驱动到数据驱动&#xff0c;降低情绪、心理等主观影响&#xff0c;形成以数据为基础的业务决策支撑&#xff0c;提高决策…

C++入门(内容补充)

目录 前言 1.auto关键字 1.1 auto的使用细则 1.2 auto不能推导的场景 2. 基于范围的for循环(C11) 2.1 范围for的使用条件 3.指针空值nullptr(C11) 3.1 C98中的指针空值 前言 之前给大家更新了一系列关于C的基础语法&#xff0c;那么今天小编再给大家进行部分内容的补充…

【C++】线程库

文章目录 线程库&#xff08;thread&#xff09;线程安全锁实现两个线程交替打印1-100 线程库&#xff08;thread&#xff09; 在C11之前&#xff0c;涉及到多线程问题&#xff0c;都是和平台相关的&#xff0c;比如Windows和Linux下各有自己的接口&#xff0c;这使得代码的可…

python函数的递归调用

引入 函数既可以嵌套定义也可以嵌套调用。嵌套定义指的是在定义一个函数时在该函数内部定义另一个函数&#xff1b;嵌套调用指的是在调用一个函数的过程中函数内部有调用另一个函数。而函数的递归调用指的是在调用一个函数的过程中又直接或者间接的调用该函数本身。 函数递归…

Python入门(三)变量和简单数据类型(二)

变量和简单数据类型&#xff08;二&#xff09; 1.数1.1 整数操作1.2 浮点数操作1.3 整数和浮点数1.4 数中的下划线1.5 同时给多个变量赋值1.6 常量 2.注释2.1 如何编写注释2.2 编写什么样的注释 作者&#xff1a;Xiou 1.数 数在编程中是经常使用的一种数据类型&#xff0c;可…

【目标检测论文阅读笔记】Dynamic Head: Unifying Object Detection Heads with Attentions

Abstract 在目标检测中结合定位和分类的复杂性导致了方法的蓬勃发展。以前的工作试图提高各种目标检测头的性能&#xff0c;但未能提出统一的观点。在本文中&#xff0c;我们提出了一种新颖的动态头部框架 来统一目标检测头部和注意力。通过在用于尺度感知的特征级别之间、用于…

嵌入式Linux:FrameBuffer 和 DRM/KMS(一)

文章目录 前言: Linux 的两种显示方案FrameBufferDRM1、GEM2、KMS 参考&#xff1a;RK3399 探索之旅 / Display 子系统 / 基础概念 参考&#xff1a;DRM架构介绍&#xff08;一&#xff09; 前言: Linux 的两种显示方案 包括&#xff1a; FBDEV: Framebuffer Device DRM/KM…

【MediaSoup c#】 worker的创建

js rust 不太熟,c# 似乎还好懂一些。学习media soup 的各个组件及大体使用方式学习其设计理念。MediasoupServer 管理worker列表 worker的表达是通过 IWorker 抽象类 拥有一个observer 实例 (EventEmitter): /// <summary>/// Observer instance./// </summary&g…

顺序表和链表优缺点以及区别

顺序表和链表的区别 顺序表优点缺点 链表优点缺点 顺序表和链表不同点 顺序表 优点 1.尾插尾删效率高 2.支持随机访问 3/相比于链&#xff0c;cpu高速缓存命中率更高 缺点 1.在头部和中部插入删除效率底 2.需要大片连续空间&#xff0c;改变容量不方便 链表 优点 1.不需要…

【嵌入式Linux驱动】驱动开发调试相关的关系记录

https://www.processon.com/mindmap/64537772b546c76a2f37bd2f

MySQL概述 -- 数据模型SQL简介DDL数据库操作

一. 数据模型 介绍完了Mysql数据库的安装配置之后&#xff0c;接下来我们再来聊一聊Mysql当中的数据模型。学完了这一小节之后&#xff0c;我们就能够知道在Mysql数据库当中到底是如何来存储和管理数据的。 在介绍 Mysql的数据模型之前&#xff0c;需要先了解一个概念&#x…

SPSS如何进行对应分析之案例实训?

文章目录 0.引言1.对应分析2.多重对应分析 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对SPSS进行了学习&#xff0c;本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结&#xff0c;本文对对应分析进行阐述。 1.对应分析 &#…

混合策略改进的金枪鱼群优化算法(HTSO)-附代码

混合策略改进的金枪鱼群优化算法(HTSO) 文章目录 混合策略改进的金枪鱼群优化算法(HTSO)1.金枪鱼群优化算法2. 改进金枪鱼群优化算法2.1 Circle混沌映射初始化种群Circle2.2 Levy flight改进螺旋式觅食 3.实验结果4.参考文献5.Matlab代码6.Python代码 摘要&#xff1a;针对金枪…

操作系统考试复习——第三章 进程调度和实时调度

进程调度的方式分为&#xff1a;抢占式和非抢占式 采用非抢占式时&#xff0c;一旦把处理机分配给某进程后&#xff0c;就让他一直运行下去&#xff0c;决不会因为时钟中断或其他任何原因去抢占当前正在运行进程的处理机。直至该进程完成或因为某件事情堵塞&#xff0c;才把处…

MMediting1.X进行视频超分训练和测试(BasicVsr++)

因为MMediting更新了版本&#xff0c;整体的变化比较大&#xff0c;导致之前的一些介绍操作的帖子不太适合新手入门&#xff0c;这里以作者自己对BasicVsr模型进行测试和训练的过程&#xff0c;写一下具体的操作过程。 &#xff08;1&#xff09;找到模型     首先在config…

JavaScript判断是否为NaN

&#xff08;旅行是最劳顿&#xff0c;最麻烦&#xff0c;叫人本相必现的时候。经过长期苦旅行而彼此不讨厌的人&#xff0c;才可以结交作朋友。——钱钟书&#xff09; 为什么NaN在js值得一提 相信你在实际开发中&#xff0c;经常遇到一下场景 const pasNumber parseInt(un…