C语言中链表中经典面试题

news2024/10/6 9:22:33

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

移除链表元素

反转链表 

合并两个有序链表 

总结 


移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

提示:

  • 列表中的节点数目在范围 [0, 104] 内
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

解题思路:

解题的关键在于我们需要大致判断链表的几种情况,然后通过调试,一步一步通过测试用例,这里我们可以分为三种链表,第一种就是链表为空,这种直接返回空指针,第二种就是链表的第一个节点的val值等于测试用例的val,这里我们就需要进行换头处理,就是跳过第一个节点,把第二个节点当作头,第三种val值在链表非头的位置,从头开始寻找,找到等于val的节点,将val的上个节点连接到val的下个节点。因为我们需要知道val的前后两个节点,所以采用双指针的方法

struct ListNode* removeElements(struct ListNode* head, int val)
{
    //这就是第一种情况,如果头为空,直接返回空值
    if(head==NULL)
    {
        return NULL;
    }
    struct ListNode* prev=NULL,*cur=head;//双指针的方法,一前一后的指针
    while(cur)//通过循环遍历整个链表
    {
        if(cur->val==val)
        {
            if(prev==NULL)
            {
                cur=cur->next;
                head=cur;
            }
            else
            {
                prev->next=cur->next;
                cur=cur->next;
            }
        }
        else
        {
            prev=cur;
            cur=cur->next;
        }
    }
    return head;
}

反转链表 

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

解题思路:

解题的关键在于我们需要大致判断链表的几种情况,然后通过调试,一步一步通过测试用例,这题分为两种情况,第一种链表为空的时候,就直接返回空指针,第二种链表不为空时,我们采用的是在原有的链表上进行改动,就是将原有的节点指向改变,这里需要记录三个节点的位置,所以需要三个指针

struct ListNode* reverseList(struct ListNode* head)
{
    if(head==NULL)
    {
        return NULL;
    }
    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;
}

合并两个有序链表 

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

提示:

  • 两个链表的节点数目范围是 [0, 50]
  • -100 <= Node.val <= 100
  • l1 和 l2 均按 非递减顺序 排列

解题思路:

解题的关键在于我们需要大致判断链表的几种情况,然后通过调试,一步一步通过测试用例,这个链表分为四种情况,第一种list1为空时,直接返回list2,第二种list2为空时,直接返回list1,第三种list1和list2都为空时,直接返回空指针,第四种list1和list2都不为空时,首先我们的需要一个头指针去保存头节点的位置,我们需要去判断list1和list2的头节点的val值大小情况,谁小就让头指针去指向谁,然后,我们需要遍历两个链表,只要其中一个链表为空,就跳出循环

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* cur=NULL;
    struct ListNode* head=NULL;
    while(list1&&list2)
    {
        if(list1->val<list2->val)
        {
            if(head==NULL)
            {
                head=cur=list1;
            }
            else
            {
                cur->next=list1;
                cur=list1;
            }
            list1=list1->next;
        }
        else
        {
             if(head==NULL)
            {
                head=cur=list2;
            }
            else
            {
                cur->next=list2;
                cur=list2;
            }
            list2=list2->next;
        }
    }
    if(list1==NULL)
    {
        cur->next=list2;
    }
     if(list2==NULL)
    {
        cur->next=list1;
    }
    return head;
}

总结 

做链表的题的确需要一番思索,我在做第一个题的时候,做了大概两天时间,但还是没有完全通过测试用例(可能我比较愚笨),我就放弃了这道题。过了几天我重新去做这道题,通过了一些方法,最终解决了这道题。这些方法我归结了一下,可以适用于大部分链表类的测试题,第一:画图!画图!画图!重要的事情说三遍,我感觉之所以之前没有做出来这道题,是我没有认真画图的原因,认真画图非常关键,为什么强调认真画图,我之前做题的时候,就老是把图画的很乱,而且画图的位置空间也不足,导致有时候一次测试用例都没有走完,我就放弃了,后来做题过程中,我就认认真真画图,然后走完了几个测试用例,我就这样完成了这道题。第二:有时候我们感觉逻辑没有问题,但是还是存在错误,我们就需要进行调试了,因为这些题目是在线OJ题,一般是不能调试的,所以我们需要在自己的编译器上进行调试,进行调试后,我们就能很容易的到出错的位置,这样有助于我们完成这道题。

🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸   

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

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

相关文章

扩展 VirtualBox 已分配磁盘的方法

扩展 VirtualBox 已分配磁盘的方法 第一步&#xff1a;用VirtualBox命令行调整已分配磁盘的大小第二步&#xff1a;用windows磁盘管理工具扩展磁盘空间 第一步&#xff1a;用VirtualBox命令行调整已分配磁盘的大小 "c:\Program Files\Oracle\VirtualBox\VBoxManage.exe&q…

3年经验程序员聊聊外包项目,总结了6个典型的问题该如何解决

我是一名老程序员&#xff0c;接了项目&#xff0c;接外包项目已经有3年多的经验了。今天我想分享一些接项目的经验给大家。 第一&#xff0c;辞职去接外包&#xff0c;好吗&#xff1f;有很多人幻想辞职了全职去接外包&#xff0c;但我并不太建议这样做。我建议大家先把自己的…

计算机基础必读书籍

一、计算机组成原理 思维导图&#xff1a; 1、计算机系统概述 主要讲授信息的数字化表示、存储程序与冯诺依曼体制&#xff1b;计算机的诞生和发展&#xff1b;计算机系统的层次结构和硬件系统组织&#xff1b;计算机的主要性能指标。 2、数据的表示、运算与校验 主要讲授数值…

一个go http和grpc客户端库

大家好&#xff0c;我是peachesTao&#xff0c;今天是五一假期的第4天&#xff0c;首先祝大家劳动节快乐。今天给大家推荐一个统一http和grpc客户端调用的库&#xff0c;名为prpc&#xff0c;github地址&#xff1a;prpc&#xff0c;该库是我公司根据最佳实践总结开发出来的&am…

【C++进阶之路】类和对象(上)

文章目录 一.面向对象和面向过程二.类的引入——结构体三.类的定义1.类定义的两种方式在类里面定义函数在类外定义函数——类域 2.访问限定符3.封装——面向对象的三大特性4.类的实例化 四.类对象模型求一个类的大小 五.this指针基本认识代码解读 一.面向对象和面向过程 面向对…

【移动端网页布局】流式布局案例 ③ ( 实现搜索栏功能 | 伪元素选择器 | 子绝父相 | 外边距塌陷处理 | 二倍精灵图处理方案 )

文章目录 一、搜索栏样式及核心要点1、实现效果2、自动伸缩搜索栏实现3、搜索栏父容器设置4、搜索栏左右两侧的按钮盒子5、搜索栏盒子6、二倍精灵图处理方案 二、完整代码示例1、HTML 标签结构2、CSS 样式3、展示效果 一、搜索栏样式及核心要点 1、实现效果 上一篇博客中 , 完成…

2022年职业教育技能大赛网络安全 linux系统渗透提权

B-10&#xff1a;Linux 系统渗透提权 任务环境说明&#xff1a; ✓ 服务器场景&#xff1a;Server2202&#xff08;关闭链接&#xff09; ✓ 用户名&#xff1a;hacker 密码&#xff1a;123456 使用渗透机对服务器信息收集&#xff0c;并将服务器中 SSH 服务端口号作为 flag…

API 接口自动化测试的基本原理及实战教程

目录 常用API接口协议介绍 Http协议接口请求的介绍 HTTPS协议 SMTP协议 SNMP协议 FTP协议 API 接口自动化测试的基本原理 常用API接口协议介绍 HTTP协议 超文本传输协议 它是用来在Internet上传送超文本的传送协议&#xff0c;运行在TCP/IP协议族之上&#xff0c;它可…

Docker file镜像

目录 一、Docker镜像的创建 1、基于现有镜像创建 2、基于本地模版创建 3、基于Dockerfile创建 1、联合文件系统&#xff08;UnionFS&#xff09; ​编辑2、镜像加载原理 3、Dockerfile 4、Docker 镜像结构的分层 二、Dockerfile 操作常用的指令 &#xff08;1&#xf…

把树莓派改造成NAT软路由器

本文目录 1、查看网卡情况2、配置静态ip3、配置IP转发和SNAT功能3.1、开启Linux的报文转发功能 3.2、开启SNAT功能4、进阶配置4.1、如果WAN口(上行接口)eth0是动态分配的IP地址4.2、在LAN口上&#xff0c;给下游主机开启自动分配IP地址功能4.3、永久保存iptables, SNAT配置&…

Redis学习笔记02(主从同步,哨兵,哨兵集群)

数据同步&#xff1a;主从数据库如何保障数据一致性 redis具有高可靠性&#xff1a;1.数据尽量减少丢失&#xff08;AOF和RDB来保障&#xff09; 2.服务尽量减少中断.第二点通过增加冗余副本来保障。 读写分离&#xff1a; 减少保障数据一致性的开销。修改操作只会在主库上进…

《花雕学AI》解锁ChatGPT潜力!183个最佳提示语,助您充分利用人工智能技术

随着机器学习和自然语言处理技术的不断进步&#xff0c;人工智能在各个领域的应用越来越广泛。ChatGPT&#xff08;Generative Pre-trained Transformer&#xff09;是一个强大的自然语言生成模型&#xff0c;它可以帮助我们生成高质量的文本内容。本文为你列举了 183 种可能的…

【51单片机】DS1302时钟模块

&#x1f38a;专栏【51单片机】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Waiting For Love】 大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 目录 &#x1f354;效果 &#x1f354;代码 main.…

Stable Diffusion 本地部署教程不完全指南

ChatGPT免费体验入口网址 http://chat.xutongbao.top 参考链接&#xff1a; ERROR: Could not find a version that satisfies the requirement torch1.7.0 ERROR: No matching……_congcongiii的博客-CSDN博客 下载链接&#xff1a; https://download.pytorch.org/whl/cu11…

VMware下centos7开机登陆页面死循环问题解决

文章目录 VMware下centos7开机登陆页面死循环问题详细解决解决 VMware下centos7开机登陆页面死循环问题详细解决 脚本中有reboot重启命令 并且给该脚本加上了开机自启动 因为在脚本中没有给重启做判断&#xff0c;运行脚本后就会一直重启 解决 在VMware下centos7开机页面按e键…

【Linux】如何实现单机版QQ,来看进程间通信之管道

学会了管道&#xff0c;就可以实现简单的qq哦~ 文章目录 前言一、匿名管道总结 前言 为什么要进行进程间通信呢&#xff1f;因为需要以下这些事&#xff1a; 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 资源共享&#xff1a;多个进程之间共享同样的资源。 …

【五一创作】Linux---I2C应用编程

目录简述 前言&#xff1a; 一、I2C协议 &#xff08;1&#xff09;概述 &#xff08;2&#xff09;I2C硬件框架&#xff1a; &#xff08;3&#xff09;I2C软件框架 &#xff08;4&#xff09;I2C数据格式 二、SMBus协议 三、I2C系统重要的结构体 四、访问I2C设备&am…

欧姆龙NX/NJ系列PLC对接Oracle数据库,实现PLC与数据库双向数据通讯

智能网关IGT-DSER方便实现PLC与数据库之间的数据通讯&#xff0c;既可以读取PLC的数据上报到数据库&#xff0c;也可以从数据库查询数据后写入到PLC的寄存器。 网关安装在设备侧&#xff0c;与设备同时起停&#xff0c;不担心数据丢失&#xff1b;在断网、服务器维护上报数据有…

ID3算法报告理解笔记

专有名词解释&#xff1a; 决策树&#xff1a;决策树是根据已知若干条件&#xff0c;来对事件做出判断。从根节点到叶子结点。自上而下生成&#xff0c;每个决策或事件都可能引发两个或多个事件。将这些事件根据不同的特征进行划分&#xff0c;最后将类别分出&#xff0c;得到…

【Java校招面试】基础知识(四)——JVM

目录 前言一、基础概念二、反射三、类加载器ClassLoader四、JVM内存模型后记 前言 本篇主要介绍Java虚拟机——JVM的相关内容。 “基础知识”是本专栏的第一个部分&#xff0c;本篇博文是第四篇博文&#xff0c;如有需要&#xff0c;可&#xff1a; 点击这里&#xff0c;返回…