单链表经典OJ题(三)

目录

1、反转链表

2、合并两个有序链表

3、链表的中间结点

4、环形链表的约瑟夫问题

5、移除链表元素

6、移除元素


1、反转链表

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

翻转链表的实质就是更改当前结点的前驱结点和后继结点

假设原链表为:1->2->3->4->5->NULL,具体解题思路如下: 

由题意得,反转后的链表为NULL<-1<-2<-3<-4<-5,那么我们假设三个指针用于实现这一反转过程,其中令cur指针指向原链表的第一个结点,pre指向链表最后一个结点的下一个结点也就是空结点NULL(既然是反转链表那就要全部反转完,即使是空结点也要反转,pre其实就相当于一个引路人的作用它告诉cur你要将你所指向结点的next指针指向我所指的对象),最后令tmp指针指向cur指针指向结点的下一个结点,具体情况如下图所示:

然后我们开始反转操作,首先要将链表第一个结点的后继结点变为NULL,所以要执行的操作就是cur->next = pre,此时原链表中的1->2就变成了NULL<-1 (与1->NULL一个意思只是为了方便理解写成了前者),而pre在完成NULL的引路工作后就要进行下一个引路工作了,它的下一个引路工作就是将1->2变为1<-2,所以他这时就要指向1,也就是cur此时指向的结点,所以此时令pre=cur即可,循环的最后为了防止链表只有一个结点就结束了,所以此时仍需令cur向前走一步然后再跳出循环,即令cur=tmp,这样就可以做到在下次循环开始时可以对下一个要操作的结点是否为空进行一个判断,如果不为空才能进入循环。

关于后续几次循环,具体操作过程不再过多赘述仅以以下图片展示每次循环后的结果:

 至此链表反转完成(虽然看着怪怪的但是的确是正确的)

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/struct ListNode* reverseList(struct ListNode* head) {struct ListNode* pre = NULL;struct ListNode* cur = head;while (cur) {struct ListNode* next = cur->next;cur->next = prev;pre = curr;cur = next;}return pre;
}

2、合并两个有序链表

21. 合并两个有序链表 - 力扣(LeetCode)​​​​​​​

具体解题思路如下: 

1、合并两个链表首先要保证两个链表都不为空,如果其中一个链表为空那么合并后的结果就是另一个非空链表:

//当传入的两个链表其中有一个为空,那么返回另一个链表即可if(list1 == NULL){return list2;}if(list2 == NULL){return list1;}

 2、如果两个链表都不为空,那么分别创建两个指针指向两个链表的头结点开始遍历两个链表,同时还要创建一个用于存放两个旧链表合并结果的新链表,我们这里创建一个带有哨兵位的单向链表这样后续进行尾插等操作就不需要考虑头结点是否为空的情况,减少重复代码

//当两个链表都不为空时,遍历链表
LSNode* cur1 = list1;
LSNode* cur2 = list2;LSNode* newHead,*newTail;
newHead = newTail = (LSNode*)malloc(sizeof(LSNode));
newHead->val = -1;
newHead->next = NULL;

3、开始正式遍历两个旧链表,在遍历过程中需要注意的是只要有一个链表走到了头即cur1或cur2指向空那么就不能再循环了,在都没有走到头的时候,我们就判断cur1和cur2指向的结点的值的大小,如果cur1->val < cur2->val,就将此时cur1指向的结点尾插进新链表,如果cur1->val >= cur2->val,就将此时cur2指向的结点尾插进新链表(记得每次尾插过后新链表中的newTali也就负责指向新链表最后一个有效结点的指针要向后移动以便于下一次的尾插)

 //当两个结点有一个走到空就不能进行比较了while(cur1 && cur2){//把值小的结点尾插到新的链表if(cur1->val < cur2->val){newTail->next = cur1;newTail = newTail->next;cur1 = cur1->next;}//当cur2->val <= cur1->val时else{newTail->next = cur2;newTail = newTail->next;cur2 = cur2->next;}}

4、尾插结束后,如果cur2先指向空,那么就让cur1的后续结点尾插进新链表,如果cur1先指向空,那么就让cur2的后续结点尾插进新链表,如果cur1和cur2同时指向空,证明合并完成直接返回哨兵位的下一个结点作为新链表的头结点即可,同时记得释放为哨兵位申请的内存空间

if(cur1)newTail->next = cur1;
if(cur2)newTail->next = cur2;return newHead->next;
free(newHead);

最终代码如下: 

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/typedef struct ListNode LSNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{//当传入的两个链表其中有一个为空,那么返回另一个链表即可if(list1 == NULL){return list2;}if(list2 == NULL){return list1;}//当两个链表都不为空时,遍历链表LSNode* cur1 = list1;LSNode* cur2 = list2;//创建新的空链表--带头(结点)单向不循环链表(后续进行尾插等情况就不需要考虑头结点是否为空的情况,减少重复代码)LSNode* newHead,*newTail;newHead = newTail = (LSNode*)malloc(sizeof(LSNode));newHead->val = -1;newHead->next = NULL;//当两个结点有一个走到空就不能进行比较了while(cur1 && cur2){//把值小的结点尾插到新的链表if(cur1->val < cur2->val){newTail->next = cur1;newTail = newTail->next;cur1 = cur1->next;}//当cur2->val <= cur1->val时else{newTail->next = cur2;newTail = newTail->next;cur2 = cur2->next;}}if(cur1)newTail->next = cur1;
if(cur2)newTail->next = cur2;return newHead->next;
free(newHead);
}

3、链表的中间结点

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

利用快慢指针的特性即可解决该题目:如果链表有效结点个数为单数,则当快指针指向的结点为空或快指针指向的下一个结点为空时,慢指针指向该链表的中间结点。如果链表有效结点个数为双数,则当快指针指向的结点为空或快指针指向的下一个结点为空时,慢指针指向该链表的中间两个结点的后一个结点

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/typedef struct ListNode LSNode;
struct ListNode* middleNode(struct ListNode* head)
{   if(head == NULL)return NULL;//快慢指针LSNode* slow,*fast;slow = fast = head;//只要fast和fast->next有一个为空则停止循环while(fast && fast->next){slow = slow->next;fast = fast->next->next;}//当循环结束时,slow必定指向我们要找的链表中间结点return slow;
}

4、删除有序数组中的重复项

26. 删除有序数组中的重复项 - 力扣(LeetCode)

假设有序数组为{0,0,1,1,1,2,2,3,3,4},具体解题思路如下:

1、由于官方规定该题目的数组长度numsize大于等于1,所以不需要判0操作

2、初始化两个变量fast和slow为1,令它们两个充当数组下标(这里的fast和slow貌似虽然不是快慢指针但是作用类似),题目要求返回删除数组中重复项后新数组的长度,从官方给我们的多个实例中可以发现数组中的重复项都是相连的,因此我们可以通过覆盖重复项的操作来达到删除重复项的目的,及利用重复项后的数组元素覆盖掉重复的项(如果重复项后的元素也是重复项那就用它后面的数组元素继续覆盖它),而达成这一目的之前我们要保证的是这两个相邻的元素都不相同,如果相同那么就不能执行覆盖操作,需要继续寻找与之不同的元素将其覆盖掉才行

最终代码如下:

int removeDuplicates(int* nums, int numsSize)
{int fast = 1, slow = 1;while (fast < numsSize) {if (nums[fast] != nums[fast - 1]) {nums[slow] = nums[fast];++slow;}++fast;}return slow;
}

5、移除链表元素 

203. 移除链表元素 - 力扣(LeetCode)​​​​​​​

emm这道题很简单直接看注释即可......

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/typedef struct ListNode LSNode;
struct ListNode* removeElements(struct ListNode* head, int val){//还是申请哨兵位的老套路LSNode* newHead,*newTail;newHead = newTail = (LSNode*)malloc(sizeof(LSNode));newHead->val = -1;newHead->next = NULL;//令新指针pcur指向原链表的头结点head,遍历原链表LSNode* pcur = head;while(pcur){//当不满足.val==val时,开始向新建的空链表中插入if(pcur->val != val){//1、如果新建的链表为空,插入的新节点就是链表的头结点和尾结点if(newHead == NULL){newHead = newTail = pcur;}//2、如果新建的链表不为空,直接尾插,让新插进来的结点作为新的尾结点else{newTail->next = pcur;newTail = newTail->next;}}//当满足pcru->val = val,直接跳过进行下一个读取即可,这一点可以看题目中给的示例得到pcur = pcur->next;}//pcur指向NULL时跳出while循环,此时newTail->next指向的位置仍是旧链表存储数据6的结点,所以此时需要再判断newTail是否为空,如果不为空则让它最后指向的方向置为空,最后再返回哨兵位的下一个结点if(newTail)newTail->next = NULL;return newHead->next;free(newHead);
}

6、移除元素

27. 移除元素 - 力扣(LeetCode)

具体解题思路如下: 

1、声明并初始化两个变量 src 和 dst,分别表示源索引和目标索引。初始时,两者都为 0。

2、若当前位置上的元素等于目标值即 nums[src] == val,则增加源索引(跳过需要移除的元素)

3、若当前位置上的元素不等于目标值,则将当前位置上的元素复制到目标位置 nums[dst] = nums[src],同时增加源索引和目标索引(二者都向后走)

4、循环结束后,返回目标索引作为新数组长度

主要是通过遍历原始数组,将非目标值复制到新的位置来实现删除指定元素。它使用两个指针(其实也不算是指针)来追踪读取和写入操作,并根据是否遇到要删除的值来控制它们如何前进。最终达到将非目标值移到前面、覆盖掉要删除项并计算出新数组的长度的目标

具体代码如下:

int removeElement(int* nums, int numsSize, int val)
{int left = 0, right = numsSize;while (left < right) {if (nums[left] == val) {nums[left] = nums[right - 1];right--;} else {left++;}}return left;
}

~over~

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

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

相关文章

【nlp】2.4 GRU模型

GRU模型 1 GRU介绍2 GRU的内部结构图2.1 GRU结构分析2.2 Bi-GRU介绍2.3 使用Pytorch构建GRU模型2.4 GRU优缺点3 RNN及其变体1 GRU介绍 GRU(Gated Recurrent Unit)也称门控循环单元结构, 它也是传统RNN的变体, 同LSTM一样能够有效捕捉长序列之间的语义关联, 缓解梯度消失或爆…

Day29力扣打卡

打卡记录 美丽塔 II&#xff08;前后缀分解 单调栈&#xff09; 链接 大佬的题解 class Solution:def maximumSumOfHeights(self, a: List[int]) -> int:n len(a)suf [0] * (n 1)st [n] # 哨兵s 0for i in range(n - 1, -1, -1):x a[i]while len(st) > 1 and …

​TechSmith Camtasia 2024破解版功能介绍及使用教程

在现在的网络互联网时代&#xff0c;越来越多的人走上了自媒体的道路。有些自媒体人会自己在网络上录制精彩视频&#xff0c;也有一些人会将精彩、热门的电影剪辑出来再加上自己给它的配音&#xff0c;做成大家喜欢看的电影剪辑片段。相信不管大家是自己平时有独特的爱好也好、…

Django(五、视图层)

文章目录 一、视图层1.视图函数返回值的问题2.三板斧的使用结论&#xff1a;在视图文件中写视图函数的时候不能没有返回值&#xff0c;默认返回的是None&#xff0c;但是页面上会报错&#xff0c;用来处理请求的视图函数都必须返回httpResponse对象。 二、JsonReponse序列化类的…

[单片机课程设计报告汇总] 单片机设计报告常用硬件元器件描述

[单片机课程设计必看] 单片机设计报告常用描述 硬件设计 AT89C51最小系统 AT89C51是美国ATMEL公司生产的低电压&#xff0c;高性能CMOS16位单片机&#xff0c;片内含4k bytes的可反复擦写的只读程序存储器和128 bytes的随机存取数据存储器&#xff0c;期间采用ATMEL公司的高…

FreeRTOS源码阅读笔记3--queue.c

消息队列可以应用于发送不定长消息的场合&#xff0c;包括任务与任务间的消息交换&#xff0c;队列是 FreeRTOS 主要的任务间通讯方式&#xff0c;可以在任务与任务间、中断和任务间传送信息&#xff0c;发送到 队列的消息是通过拷贝方式实现的&#xff0c;这意味着队列存储…

Python入门:一文详解Python列表(List)操作方法

文章目录 前言一、创建一个列表二、访问列表中的值三、更新列表四、删除列表元素六、Python列表截取七、Python列表操作的函数和方法关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②…

部署百川大语言模型Baichuan2

Baichuan2是百川智能推出的新一代开源大语言模型&#xff0c;采用 2.6 万亿 Tokens 的高质量语料训练。在多个权威的中文、英文和多语言的通用、领域 benchmark 上取得同尺寸最佳的效果。包含有 7B、13B 的 Base 和 Chat 版本&#xff0c;并提供了 Chat 版本的 4bits 量化。 模…

网络运维Day16

文章目录 Docker简介什么是容器命名空间&#xff1a; Docker 的优缺点 Docker安装Docker镜像管理什么是镜像镜像管理 Docker容器管理运行容器容器启动、停止、重启拷贝文件进入容器容器与应用 DockerfileDockerfile 语法案例 总结 Docker简介 什么是容器 容器是用来装东西的&a…

Python-Python高阶技巧:HTTP协议、静态Web服务器程序开发、循环接收客户端的连接请求

版本说明 当前版本号[20231114]。 版本修改说明20231114初版 目录 文章目录 版本说明目录HTTP协议1、网址1.1 网址的概念1.2 URL的组成1.3 知识要点 2、HTTP协议的介绍2.1 HTTP协议的概念及作用2.2 HTTP协议的概念及作用2.3 浏览器访问Web服务器的过程 3、HTTP请求报文3.1 H…

红队专题-从零开始VC++C/S远程控制软件RAT-MFC-超级终端

红队专题 招募六边形战士队员[16]超级终端(1)消息 宏的定义映射cmdshell.cpp重载 构造函数Onsize 随窗口大小事件回车键发送命令添加字符转换类 StringToTransform [17]超级终端(2)接受命令创建m_cmd c类发送 接收客户端远端进程关闭 招募六边形战士队员 一起学习 代码审计、安…

景联文科技:驾驭数据浪潮,赋能AI产业——全球领先的数据标注解决方案供应商

根据IDC相关数据统计&#xff0c;全球数据量正在经历爆炸式增长&#xff0c;预计将从2016年的16.1ZB猛增至2025年的163ZB&#xff0c;其中大部分是非结构化数据&#xff0c;被直接利用&#xff0c;必须通过数据标注转化为AI可识别的格式&#xff0c;才能最大限度地发挥其应用价…

网络运维Day17

文章目录 什么是数据库MySQL介绍实验环境准备构建MySQL服务连接数据库修改root密码 数据库基础常用的SQL命令分类SQL命令使用规则MySQL基本操作创建库创建表查看表结构 记录管理命令 数据类型数值类型 数据类型日期时间类型时间函数案例枚举类型 约束条件案例修改表结构添加新字…

C++二分查找算法:最大为 N 的数字组合

涉及知识点 二分查找 数学 题目 给定一个按 非递减顺序 排列的数字数组 digits 。你可以用任意次数 digits[i] 来写的数字。例如&#xff0c;如果 digits [‘1’,‘3’,‘5’]&#xff0c;我们可以写数字&#xff0c;如 ‘13’, ‘551’, 和 ‘1351315’。 返回 可以生成的…

基于群居蜘蛛算法优化概率神经网络PNN的分类预测 - 附代码

基于群居蜘蛛算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于群居蜘蛛算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于群居蜘蛛优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

python语言的由来与发展历程

Python语言的由来可以追溯到1989年&#xff0c;由Guido van Rossum&#xff08;吉多范罗苏姆&#xff09;创造。在他的业余时间里&#xff0c;Guido van Rossum为了打发时间&#xff0c;决定创造一种新的编程语言。他受到了ABC语言的启发&#xff0c;ABC语言是一种过程式编程语…

PHP 服装销售管理系统mysql数据库web结构layUI布局apache计算机软件工程网页wamp

一、源码特点 PHP 服装销售管理系统是一套完善的web设计系统mysql数据库 &#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 php服装销售管理系统1 二、功能介绍 (1)员工管理&#xff1a;对员工信息…

【电子通识】USB端口颜色编码标识

不知道你有没有发现 USB 口有不同的颜色&#xff0c;黑色、蓝色、紫色、红色、黄色等等&#xff0c;你知道不同颜色的 USB 口各代表什么意思吗&#xff1f; 这些颜色不是USB规范所要求的&#xff0c;设备制造商之间也不一致。例如&#xff0c;Intel使用橙色表示充电端口&#…

DAY54 392.判断子序列 + 115.不同的子序列

392.判断子序列 题目要求&#xff1a;给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是…

科研学习|科研软件——有序多分类Logistic回归的SPSS教程!

一、问题与数据 研究者想调查人们对“本国税收过高”的赞同程度&#xff1a;Strongly Disagree——非常不同意&#xff0c;用“0”表示&#xff1b;Disagree——不同意&#xff0c;用“1”表示&#xff1b;Agree--同意&#xff0c;用“2”表示&#xff1b;Strongly Agree--非常…