单链表经典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.hqwc.cn/news/174440.html

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

相关文章

【教3妹学编辑-mysql】mybatis查询条件遇到的坑及解决方案

2哥 :3妹&#xff0c;今天怎么下班这么晚啊。 3妹&#xff1a;嗨&#xff0c;别提了&#xff0c;今天线上出bug了&#xff0c; 排查了好久。 2哥&#xff1a;啊&#xff0c;什么问题呀&#xff1f; 3妹&#xff1a;我们内部的一个管理系统报错了&#xff0c; 最近排查下来是myb…

[CANN训练营]UART通信笔记

文章目录 前言一、前提知识1.串行通信2.并行通信3.单工、半双工、全双工通信3.1单工通信3.2半双工通信3.3全双工通信 4.补充&#xff1a;通信速率 二、UART通信1.UART通信2.UART工作原理 总结 前言 在ROS学习中&#xff0c;我们在入门基础除了ROS的小乌龟外&#xff0c;在通信…

YOLOV5中parser参数配置

源码下载链接&#xff1a;ultralytics/yolov5: YOLOv5 &#x1f680; in PyTorch > ONNX > CoreML > TFLite (github.com) 需要配置的参数&#xff1a;--data parser.add_argument(--data, ...)&#xff1a;添加一个用于数据配置文件的路径的参数。 可以直接修改&am…

【算法|动态规划 | 区间dp No.1】AcWing 282. 石子合并

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【AcWing算法提高学习专栏】【手撕算法系列专栏】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&a…

视频封装格式

FLV&#xff08;Flash Video&#xff09; FLV封装格式 Tag Data分为Audio&#xff0c;Video&#xff0c;Script三种 TS&#xff08;Transport Stream&#xff09;传输流 TS文件分为三层&#xff0c;&#xff08;倒叙更好理解&#xff09; TS层&#xff1a;在PES层基础上加入…

易点易动固定资产管理系统助您轻松应对复杂的固定资产管理挑战

在现代企业运营中&#xff0c;固定资产是企业的重要财产&#xff0c;对于企业的发展和运营至关重要。然而&#xff0c;随着企业规模的扩大和业务的复杂化&#xff0c;固定资产管理面临着越来越多的挑战。传统的手工管理方法已经无法满足企业的需求&#xff0c;因此&#xff0c;…

蒙特卡洛树搜索(Monte Carlo Tree Search)揭秘

一. 什么是蒙特卡洛树搜索 蒙特卡洛树搜索(MCTS)是一种启发式搜索算法&#xff0c;一般用在棋牌游戏中&#xff0c;如围棋、西洋棋、象棋、黑白棋、德州扑克等。MCTS与人工神经网络结合&#xff0c;可发挥巨大的作用&#xff0c;典型的例子是2016年的AlphaGo&#xff0c;以4:1…

viple模拟器使用(一):线控模拟

(1)unity模拟器 通过viple程序&#xff0c;将viple编写逻辑运行在unity模拟器中。 首先编写viple程序&#xff0c;逻辑&#xff1a;设置一个机器人主机&#xff0c;并且&#xff0c;按↑、↓、←、→方向键的时候&#xff0c;能分别控制模拟机器人在unity模拟器中运行。 主机…

【软考篇】中级软件设计师 第二部分(一)

中级软件设计师 第二部分&#xff08;一&#xff09; 八. 层次化结构8.1 局部性原理8.2 体系8.3 分类8.3.1 存取方式8.3.2 工作方式 8.4 Cache8.4.1 例题 8.5 地址映像 九. 主存编址9.1 例题一 十. 可靠性10.1 串联系统和并联系统 十一. 网络安全11.1 保密性11.2 完整性&#x…

蓝桥杯每日一题2023.11.13

题目描述 蓝桥杯大赛历届真题 - C 语言 B 组 - 蓝桥云课 (lanqiao.cn) 题目分析 由于每次吹灭的蜡烛与年龄相同故我们想到使用前缀和可以让我们求出各个区间的和&#xff0c;我们将每个区间都枚举一遍&#xff0c;如果符合要求就输出区间开始的位置&#xff08;答案&#xff…

linux之IPC

linux之IPC 什么是IPC共享内存(shm)ftokshmgetshmatshmdtshmctl 消息队列msggetmsgrcvmsgsndmsgctl 旗语(信号量)semgetsemctlsemopsem三级标题三级标题 ipc命令守护进程查看守护进程 什么是IPC IPC: Inter(内核) Process(进程) Communicton&#xff08;通信&#xff09; 共享内…

问AI经历网是什么

为AI生成的文案点赞 &#x1f44d;