【数据结构】链表OJ面试题(题库+解析)

前言

还不清楚链表的码喵们可以看看前篇关于链表的详解

http://t.csdnimg.cn/X6t6P


1.链表面试题

既然已经懂得了链表该如何实现,那么现在就趁热打铁开始练习!这里给码喵们整理了相对不错的一些OJ题来练习

1. 删除链表中等于给定值 val 的所有结点。

 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

思路:遍历整个表,访问每个表的值并且删除再将next的指针指向下一个节点

此题比较简单,但是有几个要点来考虑:

  1. 如果第一位是需要删除的数

  2. 执行删除时要如何保存此值的地址来进行空间释放

  3. 等于val值执行删除

  4. 不等于val的值执行向下遍历

附原代码

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* removeElements(struct ListNode* head, int val){struct ListNode *tail=head;struct ListNode *prev=NULL; //用于记录节点在free掉的时候避免找不到while(tail!=NULL)   //不为尾节点向后遍历{if(tail->val == val)    //如果第一位是需要删除的数{if(tail==head){head=tail->next;free(tail);tail = head;}else                //执行删除节点,并且free掉空间避免空指针或溢出{prev->next = tail->next;free(tail);tail = prev->next;}}else{prev = tail;tail=tail->next;}}return head;}

2. 反转一个单链表。

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

本题有些难度,但是掌握好方法后类似的题就能做到运筹帷幄(决胜千里之外)

做题的要点是画图

万事开头难,掌握方法微妙,刚开始我做这题的时候想的是把他变成一个循环指针然后再标记头指针并且实现反转,不知道这样的办法大家有没有试过哈哈,现在我们来用更简单的方法吧。

我们来指定三个指针,前两个指针用于将前一个的指针记录并且连接,第三个指针负责向后遍历直到为空

方法1

定义三个指针

n1滞空用于将头指针变成新链表的尾指针,所以滞空

n2 ,n3向后遍历

首先我们让n2的下一个结点指向n1,实现第二和第一个节点的相连,再让n2=n3改变n2的地址,再让n3向下一个节点移动

n3再向下一个节点移动,之后循环到n2为空地址,就完成了所有节点的反转了。

注意要点:

  1. 链表初始值为空要怎么处理
  2. 链表的n2最终到哪里才算结束反转
  3. 指针n3的下一个节点若为空怎么办(不能赋值否则会越界)

附原代码

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* reverseList(struct ListNode* head) {struct ListNode * n1,*n2,*n3;n1=NULL;n2=head;if(n2)n3=n2->next;while(n2){n2->next = n1;n1=n2;n2 = n3;if(n3)n3=n3->next;}return n1;
}

方法2

我们可以采用头插到新表的方法实现反转,头插进NULL的表,每次插入的数据就是原表按顺序遍历。

定义一个新表为空

再让原表的cur的下一个节点指向newhead,这样就实现了头插,然后我们再定义一个指针来记录原cur的下一个节点,最后再将newhead指向cur,cur指向下一个节点next.

循环这个操作,直到cur为NULL

返回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;while(cur){struct ListNode* next=cur->next;cur->next = newhead;    //指向新节点newhead = cur;cur = next;} return newhead;
}

3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

这就要运用上非常巧妙的方法了,既然上一题我们用到了三个指针,这道题我们也用指针来做,但是只用两个指针就好

方法

我们定义两个指针都在头节点向后遍历,但是一个节点一次走一步,一个节点一次走两步

当tail走到最后的节点时,head节点刚好返回的就是中间值。

注意要点:

  1. tail走两步,head走一步,返回head的地址就是中间的地址
  2. 如果tail走到尾要怎么处理

附源代码

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* middleNode(struct ListNode* head) {struct ListNode* tail = head;while(tail->next){head=head->next;tail=tail->next;if(tail->next==NULL){//head=head->next;}elsetail=tail->next;}return head;// struct ListNode* tail = head;// int count=0;// while(tail->next)// {//     count++;//     tail = tail->next;// }// if(count%2!=0)// {//     count=(count+1)/2;// }// else// count/=2;// while(count--)// {//     head=head->next;// }// return head;
}

4. 输入一个链表,输出该链表中倒数第k个结点。 

链表中倒数第k个结点_牛客题霸_牛客网

此题是上一题的升级版,方法相似,上一题是相对移动,本体是相对距离再移动

方法

这次我们定义两个指针,一个first指针先向前走k步,之后在first和tail指针一起向前走,直到first指针走到结尾,返回tail指针

注意要点

  1. first指针走到尾该如何处理
  2. 空的链表该如何处理
  3. k等于链表的长度该返回什么值(返回第一个节点)
  4. k大于链表的长度该返回什么值(不是我想思考,是nt牛客的测试用例真有这几点,吃饱撑着)

附源代码

/*** struct ListNode {*	int val;*	struct ListNode *next;* };*//*** * @param pListHead ListNode类 * @param k int整型 * @return ListNode类*/
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k)
{if (pListHead == NULL)	//链表为空直接返回NULL{return pListHead;}struct ListNode* first = pListHead;struct ListNode* tail = pListHead;while (first->next)	//直到first走到尾{while (k > 0 && first->next)	//k没减到0并且first还没走到尾进入循环{k--;	//这里用k自减1来进行k次循环的实现(k=0侧不执行)first = first->next;//if (first->next == NULL && k > 0)//{//	return NULL;//}}if (first->next == NULL&&k==1)		//当k减到1并且first已经走到尾{return tail;				//我们就可以直接返回tail的值,这就是返回第一个节点}else if(k>1)					//如果first到达尾,并且k还大于1,那就是k大于整个链表长度的情况{return NULL;				//直接返回NULL}tail = tail->next;		//tail向下走一步first = first->next;	//frist向下走一步}//tail=tail->next;return tail->next;
}// int count = k;// while(first->next)// {//     first=first->next;// }//     int len = count;// while(tail->next)// {//     while(len--)//     {//         tail=tail->next;//     }//     if(tail!=first)//     {//         len = count;//     }//     else //     {//         return pListHead->next;//     }//     pListHead = tail;// }// return 0;// write code here

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

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

方法

照图来看,我们可以很明显的知道我们可以把新的数据放入“新的“链表,这里的引号,意思是这种合并的题目,我们可以不创建新的空间,因为链表的特性,就是每个都是一块独立的空间,而我们就可以把这些表重新”排序“使之形成一个新的链表,而这里的排序方法就是:比较较小值,尾插入新表中。

新建两个链表

当新表为空时,将较小值(list1)的地址直接赋值,并且更新list1使之向后走,这里因为list1、list2相等,所以随便取一个就行。

依此类推,list2、list1对比时,list2较小,将list2赋值list3,同时更新。

最后当其中一个表(list2)所有值都赋值给新表后,在把另一个表的所有值直接尾插到新表就OK了,不管另一个表后有多少个值,都可以直接尾插并且完成链表的合并

之后返回我们记录的tail就完成了(真是功夫不负有心人啊)

注意要点:

  1. 初始创建表时,首节点为空,我们要让它赋值原表的地址,应该分类讨论
  2. 注意各表的更新
  3. 当其中一个表中所有的值都赋值完毕,另外一个表就可以全部尾插入新表中
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{struct ListNode* list3=NULL;struct ListNode* tail=NULL;if(list1==NULL){return list2;   //若其中一个表为空则返回另一个表}if(list2==NULL){return list1;   //若其中一个表为空则返回另一个表}while(list1&&list2){if(list1->val>list2->val)   //返回小的值{if(list3==NULL){tail=list3=list2;   //如果新链表没有头则把较小值的地址赋值}else{list3->next = list2;    //新链表的下一个节点指向较小值list3=list3->next;      //更新新链表}list2=list2->next;          //更新已被赋值的较小值链表首地址}else if(list1->val<list2->val){if(list3==NULL){tail=list3=list1;   //如果新链表没有头则把较小值的地址赋值}else{list3->next = list1;list3=list3->next;}list1=list1->next;}else                //两值相同则赋值其中一个链表的首地址{if(list3==NULL){tail=list3=list1;   //如果新链表没有头则把较小值的地址赋值}else{list3->next = list1;list3=list3->next;}list1=list1->next;}}   if(list1)       //其中一个表全部赋值完毕,侧再把另一个表的剩下值尾插到新表{list3->next=list1;return tail;} else if(list2){list3->next=list2;return tail;}else{return tail;}}

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

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

相关文章

【Lambda表达式和函数式接口】

目录 Lambda表达式和函数式接口的使用具有以下几个影响&#xff1a;下面是一个简单的示例代码&#xff0c;使用Lambda表达式实现一个对列表进行遍历的操作&#xff1a; 在Java 8及以上版本中&#xff0c;Lambda表达式是一种函数式编程的特性&#xff0c;它可以使代码更加简洁、…

【Tomcat与网络2】一文理解Servlet是怎么工作的

在前面&#xff0c;我们研究了如何用idea来启动一个Servlet程序&#xff0c;今天我们就再来看一下Servlet是如何工作的。 目录 1.Servlet 介绍 2.Servlet 容器工作过程 3.Servlet的扩展 不管是电脑还是手机浏览器&#xff0c;发给服务端的就是一个 HTTP 格式的请求&#xf…

微信网页授权之使用完整服务解决方案

目录 微信网页授权能力调整造成的问题 能力调整的内容和理由 原有运行方案 is_snapshotuser字段 改造原有方案 如何复现测试场景 小结 微信网页授权能力调整造成的问题 依附于第三方的开发&#xff0c;做为开发者经常会遇到第三方进行规范和开发的调整&#xff0c;如开…

【EI会议征稿通知】2024年材料物理与复合材料国际学术会议

2024年材料物理与复合材料国际学术会议 2024 International Conference on Materials Physics and Composites(ICMPC 2024) 2024年材料物理与复合材料国际学术会&#xff08;ICMPC 2024&#xff09;将于2024年5月24-26日在中国成都举行。ICMPC 2024将吸引顶尖的研究人员和从业…

Python flask 模板详解

文章目录 1 概述1.1 模板简介1.2 templates 文件1.3 简单应用 2 模板语法2.1 for 循环2.2 if 判断 3 模板的继承3.1 格式要求3.2 实现示例3.3 复用父模板的内容&#xff1a;super 1 概述 1.1 模板简介 定义&#xff1a;定义好的 html 文件&#xff0c;用于快速开发 web 页面J…

android tv开发-1,leanback 2

目录 presenter太多,如何理清关系 动画与点击 tv的登录与设置 搜索功能 带二级菜单的页面 presenter太多,如何理清关系 leanback里面已经定义好了adapter与presenter,直接继承它就可以了 private DefaultObjectAdapter mVideoAdapter; private VideoCardPresenter mCardP…

【不单调的代码】还在嫌弃Ubuntu终端?快来试试做些Ubuntu终端的花式玩法。

&#x1f38a;专栏【不单调的代码】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Love Story】 &#x1f970;大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 注意&#xff1a; 本文是在Ubuntu环境下进…

Unity中blendtree和state间的过渡

混合树状态之间的过渡 如果属于此过渡的当前状态或下一状态是混合树状态&#xff0c;则混合树参数将出现在 Inspector 中。通过调整这些值可预览在混合树值设置为不同配置时的过渡表现情况。 如果混合树包含不同长度的剪辑&#xff0c;您应该测试在显示短剪辑和长剪辑时的过渡表…

明道云入选亿欧智库《AIGC入局与低代码产品市场的发展研究》

2023年12月27日&#xff0c;亿欧智库正式发布**《AIGC入局与低代码产品市场的发展研究》**。该报告剖析了低代码/零代码市场的现状和发展趋势&#xff0c;深入探讨了大模型技术对此领域的影响和发展洞察。其中&#xff0c;亿欧智库将明道云作为标杆产品进行了研究和分析。 明…

指针的学习2

目录 数组名的理解 使用指针访问数组 一维数组传参的本质 冒泡排序 二级指针 指针数组 指针数组模拟二维数组 数组名的理解 数组名是数组首元素的地址 例外&#xff1a; sizeof(数组名),sizeof中单独放数组名&#xff0c;这里的数组名表示整个数组&#xff0c;计算的…

Day11代码随想录

Day11 20. 有效的括号 力扣题目链接(opens new window) 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串&#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右…

mac如何实现升级node版本、切换node版本

一、 查看node所有版本&#xff08;前提:安装了nodejs&#xff09; npm view node versions二、安装指定node版本 sudo n 版本号三、检查目前安装了哪些版本的node&#xff0c;会出现已安装的node版本 n四、切换已安装的node版本 sudo n 版本号其他命令 1、sudo npm cache…

PyTorch 2.2 中文官方教程(十六)

介绍 torch.compile 原文&#xff1a;pytorch.org/tutorials/intermediate/torch_compile_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 注意 点击这里下载完整的示例代码 作者: William Wen torch.compile是加速 PyTorch 代码的最新方法&#xff0…

Git快速入门+常用指令+提交规范

目录 Git创建本地仓库 IDEA集成Git Git和IDEA连接使用2 忽略文件 本地仓库常用命令 远程仓库常用命令 分支常用命令 标签操作 提交规范 Git创建本地仓库 1、创建一个文件夹&#xff0c;右键选择Git Bash Here 2、选择下列其中一个方法 方法一&#xff1a;创建初始化…

结构化/非结构化数据的介绍常用的结构化对象存储服务

一. MinIO的简介&#xff1a; 1.1 Minlo 介绍&#xff1a; Minlo 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口&#xff0c;非常适合于存储大容量非结构化的数据&#xff0c;例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等…

详解为什么现在的 LLMs 大都是 Decoder-only 的架构

首先概述几种主要的架构: Encoder-only:以谷歌的 BERT 为代表。 Encoder-Decoder:以谷歌的 T5、Meta 的 BART 为代表。 基于自回归空白填充的通用语言模型:清华大学的 GLM。 XLNet:XLNet 在那时是一种通用的自回归预训练方法。通过最大化所有可能的因式分解排列的对数似然…

鸡数题! - 组合数学 + 第二类斯特林数

题面 分析 第二类斯特林数 将每一位1看作球&#xff0c;元素看作盒子&#xff0c;直接计算。 代码 #include <bits/stdc.h>using namespace std; using ll long long;const int N 1e5 10; const int mod 1e9 7;int fact[N], infact[N];int qmi(int a, int b, in…

一篇文章了解区分指针数组,数组指针,函数指针,链表。

最近在学习指针&#xff0c;发现指针有这许多的知识&#xff0c;其中的奥妙还很多&#xff0c;需要学习的也很多&#xff0c;今天那我就将标题中的有关指针知识&#xff0c;即指针数组&#xff0c;数组指针&#xff0c;函数指针&#xff0c;给捋清楚这些知识点&#xff0c;区分…

深度解析Go字符串

Go语言中的字符串是一种不可变的字节序列&#xff0c;它在编程中扮演着重要的角色。接下来将深入探讨Go字符串的基本概念、常见操作、性能优化&#xff0c;以及最佳实践&#xff0c;旨在帮助大家更好地理解和利用Go语言中的字符串。 1. 字符串的基本概念 1.1 字符串的表示 在…

react native错误记录

第一次运行到安卓失败 Could not find implementation class com.facebook.react.ReactRootProjectPlugin for plugin com.facebook.react.rootproject specified in jar:file:/D:/Android_Studio_Data/.gradle/caches/jars-9/o_3a1fd35320f05989063e7069031b710f/react-nativ…