刷题日记 ---- 顺序表与链表相关经典算法题(C语言版)

目录

  • 1. 移除元素
  • 2. 合并两个有序数组
  • 3. 移除链表元素
  • 4. 反转链表
  • 5. 合并两个有序链表
  • 6. 链表的中间结点
  • 7. 环形链表的约瑟夫问题
  • 8. 分割链表
  • 总结


正文开始


1. 移除元素

题目链接: 移除元素

题目描述:
在这里插入图片描述
思路历程:

题目明确要求, 不能使用额外的数组空间, 也就是说不可以创建一个新的数组. 可以使用双指针法, 一个指向源数组, 一个指向目标数组, 定义两个下标, 分别从第一个元素开始向后遍历, 当src所在位置的数组值等于val时, 跳过此元素, 当src指向的数组不等于val值时, 将src位置的元素存放到dst位置, 继续向后遍历, 当遍历到数组结尾, 跳出循环, 此时dst内存放的就是不含val值的数组.

代码描述:

int removeElement(int* nums, int numsSize, int val) {int src = 0;int dst = 0;while(src<numsSize){if(nums[src] == val)src++;else{nums[dst] = nums[src];dst++;src++;}}return dst;
}

2. 合并两个有序数组

题目链接: 合并两个有序数组

题目描述:

在这里插入图片描述

思路历程:

非递减序, 即递增的序列, 定义三个指针, 分别指向第一个数组有效元素的最后一个元素, 第二个数组的最后一个元素, 第一个数组最后的一个位置, 分别为src1 , src2 , dst,
不能采用从前往后遍历, 这样会覆盖掉src1中的内容, 所以从后往前遍历, 创建三个下标, 如果第一个数组元素大于第二个数组元素就方法最后一个位置, 继续向前遍历, 反之亦然, 当跳出循环后, 如果第一个数组还有元素不必理会, 第二个数组还有元素就直接同上直接放到dst里面.

画图演示:

在这里插入图片描述

代码描述:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {int src1 = m-1;int src2 = n-1;int dst = m+n-1;while(src1>=0&&src2>=0){if(nums1[src1]>nums2[src2]){nums1[dst--] = nums1[src1--];}else{nums1[dst--] = nums2[src2--];}}while(src2>=0){nums1[dst--] = nums2[src2--];}
}

3. 移除链表元素

题目链接: 移除链表元素

题目描述:

在这里插入图片描述

思路历程:

创建一个新的链表, 遍历原链表, 当值不为val时将此节点插入到新的链表中, 为了防止出现链表为NULL会对空指针解引用, 直接创建带头链表, 给上一个哨兵位, 初始化时直接将新链表的next指向NULL, 然后开始循环遍历原链表, 值不相等的时候插入到新的链表中.

切记: 当遍历完成后将新链表的尾指针的指向改为NULL, 不然可能会出现如下情况

在这里插入图片描述

代码描述:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
#include<stdlib.h>
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {ListNode* newHead = (ListNode*)malloc(sizeof(ListNode));newHead->next = NULL;ListNode* newTail = newHead;ListNode* pcur = head;while(pcur){if(pcur->val!=val){newTail->next = pcur;newTail = newTail->next;}pcur = pcur->next;}newTail->next = NULL;return newHead->next;
}

4. 反转链表

题目链接: 反转链表

题目描述:

在这里插入图片描述

思路历程:

本题有两种思路, 第一种思路是创建一个新的链表, 将原链表头插, 不够还有另外一种更简单的思路, 直接完成原链表的翻转, 首先创建三个指针变量, 分别指向NULL, 一个元素, 和第一个元素的下一个结点, 只需要每次改变n2让他指向n1, 并且保障下一个结点地址不被丢失, 用n3来记录, 每次遍历一次之后, 继续让n2的next指向n1 , 指向完之后, 让n1 来到 n2, n2 来到n3, n3指向下一个结点.直到n2走到NULL, 此时n1即为新的链表地址.

注意: 最后一次, 当n3走到NULL, 而n2走到最后最后一个结点, 指向n1之后, n2向后走, 但是此时n3不能继续走, 会对NULL解引用,代码报错, 所以要加以判断

画图演示:
在这里插入图片描述

代码描述:

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

5. 合并两个有序链表

题目链接:合并两个有序链表

题目描述:

在这里插入图片描述

思路历程:创建一个新的链表, 带头链表防止指针为NULL,访问越界, 遍历两个链表, 比较两个链表中的val,小的结点插入到新链表中, 跳出循环后, 如果有某一个链表还有值, 直接插入到新的链表之后, 最后返回新链表的第一个有效结点, 并且释放掉自己开辟的内存.

画图演示:

在这里插入图片描述
代码描述:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*///#include<stdlib.h>typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {ListNode* newHead = (ListNode*)malloc(sizeof(ListNode));newHead->next = NULL;ListNode* newTail = newHead;while(list1 && list2){if(list1->val < list2->val){newTail->next = list1;newTail = newTail->next;list1 = list1->next;}else{newTail->next = list2;newTail = newTail->next;list2 = list2->next;}}if(list1){newTail->next = list1;}if(list2){newTail->next = list2;}ListNode* ret = newHead->next;free(newHead);newHead = NULL;return ret;
}

6. 链表的中间结点

题目链接:链表的中间结点

题目描述:

在这里插入图片描述

思路历程:

快慢指针, 定义两个指针, 慢指针一次走一步, 快指针一次走两步, 当快指针走到NULL,或者next指向NULL, 此时慢指针即为中间节点.

注意: 使用&&操作符需要先判断fast是否为NULL

画图演示:

在这里插入图片描述

代码描述:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {ListNode* slow = head;ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;
}

7. 环形链表的约瑟夫问题

题目链接: 环形链表约瑟夫问题

题目描述:

在这里插入图片描述

在这里插入图片描述
思路历程:

如果说我们采用数组的话也可以解决, 不过那太麻烦了, 可以直接创建环形链表.

在这里插入图片描述
分为两步:

第一步创建带环链表,第二步开始计数

首先创建一个带环链表, 可以使用函数创建, 完成之后返回创建好的链表的尾结点, 因为需要找到前一个结点, 返回头结点的话不知道前一个结点是啥, 接着开始计数, 当值为m时移除此节点 , 先让前一个结点的下一个位置指向待删除结点的下一个结点, 之后删除此节点, 并且让pcur指向prev所指向的结点, count从新计数, 当不等于m时,继续遍历结点, 遍历之前先让prev走到pcur保存结点, 再让pcur走到下一个结点, 计数器++,当pcur的下一个节点所指向的结点是本身的话即为要返回的结点.

画图演示:

在这里插入图片描述
代码描述:

/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param n int整型 * @param m int整型 * @return int整型*/#include <stdlib.h>
typedef struct ListNode ListNode;ListNode* buyNode(int x){ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if(newnode==NULL){perror("malloc fail");exit(1);}newnode->val = x;newnode->next = NULL;return newnode;}ListNode* creatNode(int n){ListNode* phead = buyNode(1);ListNode* ptail = phead;for(int i = 2 ; i <= n ; i++){ptail->next = buyNode(i);ptail = ptail->next;}ptail->next = phead;return ptail;}int ysf(int n, int m ) {// write code here//1.创建带环链表ListNode* prev = creatNode(n);ListNode* pcur = prev->next;int count = 1;while(pcur->next != pcur){if(count == m){prev->next = pcur->next;free(pcur);pcur = prev->next;count = 1;}else{prev = pcur;pcur = pcur->next;count++;}      }return pcur->val;
}

8. 分割链表

题目链接:分割链表

题目描述:

在这里插入图片描述

思路历程:

本题有三种思路, 其中第三种思路最为简单,创建两个带头结点的新链表, 一个用来存放大于x的结点,一个存放小于x的结点, 最后让小链表的为节点指向大链表的第一个有效位置, 最后将大链表的最后一个结点next置为NULL.返回小链表有效首结点地址.

画图演示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码描述:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/typedef struct ListNode ListNode;
struct ListNode* partition(struct ListNode* head, int x){ListNode* greaterHead = (ListNode*)malloc(sizeof(ListNode));greaterHead->next = NULL;ListNode* greaterTail = greaterHead;ListNode* lessHead = (ListNode*)malloc(sizeof(ListNode));lessHead->next = NULL;ListNode* lessTail = lessHead;ListNode* pcur = head;while(pcur){if(pcur->val >= x){greaterTail->next = pcur;greaterTail = greaterTail->next;}else{lessTail->next = pcur;lessTail = lessTail->next; }pcur = pcur->next;}greaterTail->next = NULL;lessTail->next = greaterHead->next;return lessHead->next;
}

总结

以上是对顺序链表学习中比较经典的算法题, 里面的算法思想很值得学习, 并且涵盖了一些细节和错误, 使得对顺序表和链表的理解更加深刻

如果此文有帮助, 感谢关注, 点赞 ! ! !

在这里插入图片描述

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

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

相关文章

【优质书籍推荐】AIGC时代的PyTorch 深度学习与企业级项目实战

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

springcloud按版本发布微服务达到不停机更新的效果

本文基于以下环境完成 spring-boot 2.3.2.RELEASEspring-cloud Hoxton.SR9spring-cloud-alibaba 2.2.6.RELEASEspring-cloud-starter-gateway 2.2.6.RELEASEspring-cloud-starter-loadbalancer 2.2.6.RELEASEnacos 2.0.3 一、思路 实现思路&#xff1a; 前端项目在请求后端接…

C++ 哈希

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C知识分享⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; ​ 前言 1. unordered系列关联式容器 1.1 unor…

必应bing国内广告开户注册教程!

今天搜索引擎广告成为企业推广产品与服务、提升品牌知名度的重要渠道之一。作为全球第二大搜索引擎&#xff0c;必应Bing凭借其高质量的用户群体和广泛的国际覆盖&#xff0c;为广告主提供了独特的市场机遇。在中国&#xff0c;虽然必应的市场份额相对较小&#xff0c;但对于寻…

磁密固定下的三次谐波与电压谐波的关系

同相位或者相位差为180的情况下&#xff0c;磁通密度三次谐波含量占比 α \alpha α&#xff0c;则电压三次谐波含量占比为 3 α 3\alpha 3α 同相位&#xff0c;磁通密度三次谐波含量占比 α \alpha α情况下&#xff0c; B B 0 sin ⁡ ( ω t ) α B 0 sin ⁡ ( 3 ω t )…

航空企业数字化解决方案(207页PPT)

一、资料描述 航空企业数字化解决方案是一项针对航空公司在数字化转型过程中所面临挑战的全面应对策略&#xff0c;旨在通过先进的信息技术提升航空企业的运营效率、客户服务水平以及市场竞争力。这份207页的PPT详细介绍了航空企业数字化的各个方面&#xff0c;包括关键技术的…

Web3技术解析:区块链在去中心化应用中的角色

引言 在过去几年中&#xff0c;Web3技术已经成为了互联网领域的一个热门话题。作为区块链技术的延伸&#xff0c;Web3不仅仅是数字货币的代名词&#xff0c;更是一个能够为各种应用提供去中心化解决方案的强大工具。本文将深入探讨区块链在Web3去中心化应用中的关键角色&#…

ubuntu查看opencveigen

ubuntu查看opencv&eigen&cmake版本的方法 eigen eigen版本号在/usr/include/eigen3/Eigen/src/Core/util/Macros.h文件中&#xff0c;下图代表版本3.3.7 opencv版本 pkg-config --modversion opencv4也可能最后的字符串是opencv2&#xff0c;opencv

W801学习笔记十二:掌机进阶V3版本之驱动(PSRAM/SD卡)

本次升级添加了两个模块&#xff0c;现在要把他们驱动起来。 一&#xff1a;PSRAM 使用SDK自带的驱动&#xff0c;我们只需要写一个初始化函数&#xff0c;并在其中添加一些自检代码。 void psram_heap_init(){wm_psram_config(0);//实际使用的psram管脚选择0或者1&#xff…

Java学习路线及自我规划

荒废了一段时间&#xff0c;这段时间的总结开始了JavaWeb的学习但是困难重重&#xff0c;例如Maven&#xff0c;Vue的路由等&#xff0c;所以我反省了一段时间&#xff0c;因为基础薄弱&#xff0c;加之学习的资源是速成视频&#xff0c;导致大厦将倾的局面&#xff08;也算不上…

RabbitMQ工作模式(5) - 主题模式

概念 主题模式&#xff08;Topic Exchange&#xff09;是 RabbitMQ 中一种灵活且强大的消息传递模式&#xff0c;它允许生产者根据消息的特定属性将消息发送到一个交换机&#xff0c;并且消费者可以根据自己的需求来接收感兴趣的消息。主题交换机根据消息的路由键和绑定队列的路…

盲人地图使用的革新体验:助力视障人士独立、安全出行

在我们日常生活中&#xff0c;地图导航已经成为不可或缺的出行工具。而对于盲人群体来说&#xff0c;盲人地图使用这一课题的重要性不言而喻&#xff0c;它不仅关乎他们的出行便利性&#xff0c;更是他们追求生活独立与品质的重要一环。 近年来&#xff0c;一款名为蝙蝠…

echarts地图叠加百度地图底板实现数据可视化

这里写自定义目录标题 echarts地图叠加百度地图实现数据可视化echarts地图叠加百度地图实现数据可视化 实现数据可视化时,个别情况下需要在地图上实现数据的可视化,echarts加载geojson数据可以实现以地图形式展示数据,例如分层设色或者鼠标hover展示指标值,但如果要将echa…

运筹系列91:vrp算法包PyVRP

1. 介绍 PyVRP使用HGS&#xff08;hybrid genetic search&#xff09;算法求解VRP类问题。在benchmark上的评测结果如下&#xff0c;看起来还不错&#xff1a; 2. 使用例子 2.1 CVRP COORDS [(456, 320), # location 0 - the depot(228, 0), # location 1(912, 0), …

通往AGI路上,DPU将如何构建生成式AI时代的坚实算力基石?

4月19日&#xff0c;在以“重构世界 奔赴未来”为主题的2024中国生成式AI大会上&#xff0c;中科驭数作为DPU新型算力基础设施代表&#xff0c;受邀出席了中国智算中心创新论坛&#xff0c;发表了题为《以网络为中心的AI算力底座构建之路》主题演讲&#xff0c;勾勒出在通往AGI…

Xcode 15构建问题

构建时出现的异常&#xff1a; 解决方式&#xff1a; 将ENABLE_USER_SCRIPT_SANDBOXING设为“no”即可&#xff01;

GateWay具体的使用!!!

一、全局Token过滤器 在Spring Cloud Gateway中&#xff0c;实现全局过滤器的目的是对所有进入系统的请求或响应进行统一处理&#xff0c;比如添加日志、鉴权等。下面是如何创建一个全局过滤器的基本步骤&#xff1a; 步骤1: 创建过滤器类 首先&#xff0c;你需要创建一个实现…

表---商场 nine

CREATE TABLE gao25 (id int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,shopId int(11) NOT NULL COMMENT 店铺ID,goodsId int(11) NOT NULL COMMENT 商品ID,attrId int(11) NOT NULL COMMENT 属性名称,attrVal text NOT NULL COMMENT 属性值,createTime datetime NOT NULL …

实验 1--SQL Server2008数据库开发环境

文章目录 实验 1--SQL Server2008数据库开发环境2.4.1 实验目的2.4.2 实验准备2.4.3 实验内容1.利用 SSMS 访问系统自带的Report Server 数据库。2.熟悉了解 SMSS对象资源管理器树形菜单相关选择项的功能。(1)右键单击数据库Report Server&#xff0c;查看并使用相关功能;(2)选…

[C++基础学习]----02-C++运算符详解

前言 C中的运算符用于执行各种数学或逻辑运算。下面是一些常见的C运算符及其详细说明&#xff1a;下面详细解释一些常见的C运算符类型&#xff0c;包括其原理和使用方法。 正文 01-运算符简介 算术运算符&#xff1a; a、加法运算符&#xff08;&#xff09;&#xff1a;对两个…