顺序表和单链表的经典算法题

目录

前言

一、基础思想(数组)

1. 移除元素

 2.删除有序元素的重复项

 3.合并两个有序数组

二、单链表算法

1.移除链表元素 

2.翻转链表

 3.合并两个有序的链表


 

前言

Hello,小伙伴们,今天我们来做一个往期知识的回顾,今天我将为大家讲解几道经典的顺序表和单链表算法题,来帮助大家加深对单链表知识的讲解,同时带领大家来感受一下数据结构的魅力!

如果你喜欢我的内容的话,就请不要忘了点赞,评论和收藏,你的支持就是我更新的动力,万分感谢!!

好废话不多说,开始我们今天的正题。

一、基础思想(数组)

1. 移除元素

题目链接:https://leetcode.cn/problems/remove-element/description/

我们先看这道题假设我们现在一这样的一个数组:

要让我们清除掉所有 val = 3的值,我们想一想可以怎么做呢?

1.首先我们最容易想到的就是创建一个新的数组,然后遍历整个nums,将val != 4的值都放进 

新的数组中,但是我们要注意题目中的条件,“你需要原地移除数字==val的值

也就是说,我们不能开辟新的空间。所以这个方法行不通!

2.那我们可以试试这样的方法,我们首先创建两个整型变量,d1 ,d2 = 0;

初始的状态下,是这样的

我们让d1先走,当 nums[d1] != val时

nums[d2] = nums[d1];

d1++;

d2++;

然后再当nums[d1] == val时,直接跳过该元素,后面的元素会将其覆盖掉,或者是直接失去他的访问权限;

我们画图理解一下:

当nums[d1] == val时,d1直接跳过该元素,直到nums[d1] != val 或者 走到数组的末尾。

接下来直接直接拷贝到d2上:

d2++;

nums[d2] = nums[d1]

 

同理:最后我们就可以得到去除掉val的数组了,然后我们来实现一下这个代码:

int removeElement(int* nums, int numsSize, int val) {int dest = 0;int src = 0;for (int i = 0; i < numsSize; i++)//遍历数组{if (nums[src] == val)//排除指定的元素{src++;}else//计数{nums[dest] = nums[src];dest++;src++; }}return dest;
}

 测试结果:下面是我根据这个思路对代码进行优化的结果,感兴趣的小伙伴一定要勇于挑战自己啊!!

 2.删除有序元素的重复项

题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/

 

这样的题,遇到了,我们能想出什么样的思路能?

假设我们有这样的一个 数组:

想要在题目中的条件下删除所有的重复项元素,我们能怎么办呢?

 有了上一道题的基础,我们不 难想到,先创建两个整型变量:
int d1 = 0; int d2 =  0;

我们让d1先加1

再比对nums[d1]与nums[d2];

不相等则 nums[++d2] = num[d1],然后 d1++,直到整个循环备d1遍历一遍!

好,接下来我们来实现一下代码:

int removeDuplicates(int* nums, int numsSize) {int dest = 0;int src = 1;while (src < numsSize){if (nums[dest] != nums[src] && ++dest != src)   {
//++dest != src 可以避免相等项的重复赋值!! 提高效率nums[dest] = nums[src];}src++;}return dest + 1;}

 代码测试:

 3.合并两个有序数组

题目链接:https://leetcode.cn/problems/merge-sorted-array/description/

这道题非常的有意思:

 假设我们得到这两个数组:

要注意最后的数组是,经过nums1修改后得到的,返回的数组也是nums1,不能开辟新的空间!!! 

我们可以试试这样的思路:

当 n and m都不小于0的时候,我们让nums1[n - 1] 与nums2[m - 1]比较大小

大的就放到nums1的末尾:

如图所示:

 在  m 小于0之前,一直循环遍历

 所以·我们实现代码为:

void merge(int *nums1, int n, int* nums2, int m)
{int l1 = m - 1;int l2 = n - 1;int l3 = m + n - 1;while (l1 >= 0 && l2 >= 0){if (nums1[l1] > nums2[l2]){nums1[l3--] = nums1[l1--];}else{nums1[l3--] = nums2[l2--];}}while (l2 >= 0){nums1[l3--] = nums2[l2--];}}

代码测试:

二、单链表算法

 如果还不了解单链表的同学可以先去我的另一篇博客看看单链表的知识,这对数据结构的学习有很大的帮助!!

链接:http://t.csdnimg.cn/wS03W

1.移除链表元素 

题目链接:https://leetcode.cn/problems/remove-linked-list-elements/description/

这样的题我们能相处什么样的思路呢?

也许我们可以试试这样解决问题: 

再通过比对节点中存储的数据,若不要删除的节点的数据,就直接尾插:

 

否则直接跳过:

 

在最后一定要将newtail->next == NULL,否则新链表依然会包含后面需要被删除的节点!!

接下来,我们来实现一下代码:

 typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {ListNode* newhead = NULL;ListNode* newtail = NULL;newhead = newtail = (ListNode*)malloc(sizeof(ListNode));ListNode* pcur = head;while (pcur){if (pcur->val != val){newtail->next = pcur;newtail = newtail->next;}pcur = pcur->next;}newtail->next = NULL;ListNode* ret = newhead->next;
//最后要将哨兵位释放掉, 避免空间的浪费!!!free(newhead);newhead = NULL;return ret;
}

代码测试1:

2.翻转链表

题目链接:https://leetcode.cn/problems/reverse-linked-list/description/
 

这样的题我们能用什么样的思路来写呢?

 这里作者菌,就为大家实现两种思路:
1.头插原链表

什么意思呢?我们画图来理解一下:

这样是不是就十分的清楚了:

接下来我们就可以直接来实现代码了:

 

typedef struct ListNode LN;
LN* reverseList(struct ListNode* head) {//思路1:头插原链表LN* n1, *n2;n1 = n2 = head;if (head == NULL)//这里一定要注意处理空指针的情况,也就是实例三return NULL;LN* pcur = head->next;while (pcur){LN* temp = pcur->next;pcur->next = n1;n1 = pcur;pcur = temp;}n2->next = NULL;return n1;
}

代码测试:

 接下来,我们再来学习下一个思路:

这个思路我们就直接在原链表的基础上修改指针的指向:

我们先创建三个指针:

n1 n2 n3,他们分别指向不同的位置,如图:

有了大致的思路,我们接下来要解决一些,细节性的问题:

1.三个指针到最后,哪一个指针才能成为成为最后修改后链表的头结点?

2.三指针会出现位移差,所以要注意,不要出现对NULL的解引用操作!!!

接下来我们可以来实现代码了:

 LN* n1, *n2, *n3;n1 = NULL;n2 = head;if (head == NULL)//还是要注意对NULL的处理!!return NULL;n3 = head->next;while (n2){n2->next = n1;n1 = n2;n2 = n3;if (n3)//n3会最先走到空,为了防止出现对NULL的解引用,我们要添加这一步n3 = n3->next;}return n1;
}

代码测试:

 3.合并两个有序的链表

题目链接:https://leetcode.cn/problems/merge-two-sorted-lists/description/

 这道题和我们上面的合并两个有序数组有异曲同工之妙。

我们还是可以用上面的数字比较,以此比较插入:

有了思路,我们实现代码就不难了:

 

typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if (list1 == NULL)//首先处理NULL指针的情况return list2;if (list2 == NULL)return list1;if (list1 == NULL && list2 == NULL)return NULL;ListNode* newhead, *newtail;newhead = newtail = (ListNode*)malloc(sizeof(ListNode));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;}}while (list1){newtail->next = list1;list1 = list1->next;newtail = newtail->next;}while (list2){newtail->next = list2;list2 = list2->next;newtail = newtail->next;}
//注意尾节点的next指针一定要指向NULLnewtail->next = NULL;ListNode* ret = newhead->next;//释放哨兵位,以防空间浪费!!free(newhead);newhead = NULL;return ret;
}

代码测试:

 好,今天的学习就到这里,我们下期再见,拜拜!!

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

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

相关文章

C++ 设计模式(五)——状态模式

状态模式 序言理解源码 序言 设计模式只是一个抽象的设计模式方法&#xff0c;并不是一个固定使用的搭配&#xff0c;就算是普通switch语句&#xff0c;Map&#xff0c;乃至状态机都是状态模式的其中一种实现方法 状态模式看起来好像和策略模式差不多&#xff0c;主要是其的侧…

【vluhub】log4j注入漏洞 CVE-2021-44228

LOG4介绍 是一个用Java编写的可靠&#xff0c;快速和灵活的日志框架&#xff08;API&#xff09;&#xff0c;它在Apache软件许可下发布 log4j存在远程代码执行漏洞、受影响版本2.x 部署环境 攻击机环境&#xff1a;192.168.3.180 kail环境&#xff1a;192.168.203.12【NAT…

深入理解 OSPF NSSA “P-bit”

** 注&#xff1a;机翻&#xff0c;未校对。** OSPF NSSA P-bit Explained OSPF Forward Address Filtering OSPF 转发地址过滤 In this lesson we’ll take a closer look at the OSPF NSSA “P-bit”. When we redistribute something into an OSPF NSSA area then these …

数据开发/数仓工程师上手指南(一)数仓概念总览

前言 笔者毕业最开始从事的就是大数据开发和数据仓库建设工作&#xff0c;途中曾担任过人工智能工程师和计算机视觉工程师&#xff0c;没想到最后兜兜转转还是回到了最原本的工作数据开发工程师。但很少有写关于本职工作的技术内容输出。 之前笔者撰文内容大部分都是关于算法…

C++入门基础:C++中的循环语句

循环语句是编程语言中用来重复执行一段代码直到满足特定条件的一种控制结构。它们对于处理需要重复任务的场景非常有用&#xff0c;比如遍历数组、累加数值、重复执行某项操作直到满足条件等。 但是在使用循环语句的时候需要注意下哈&#xff0c;有时候一不小心会构成死循环或者…

Ubuntu上安装anaconda创建虚拟环境(各种踩坑版)

之前都是在Windows桌面版进行深度学习的环境部署及训练&#xff0c;今天尝试了一下在Ubuntu上进行环境部署&#xff0c;踩了不少坑&#xff0c;提供一些解决办法给大家避雷。 目录 一、下载和安装anaconda 1. 下载 2. 安装 二、创建虚拟环境 一、下载和安装anaconda 1. …

uniapp入门超详细教程:如何从零开始搭建项目

目录 一、介绍 二、环境搭建 2.1.需要下载的软件 2.1.1 HBuilderX 2.1.2 下载微信开发者工具 2.2 创建uniapp项目 2.2.1 新建项目 2.2.2 项目基本结构 2.2.3 在微信开发者工具上运行 2.2.4 发布微信小程序 三、pages.json 页面路由 四、组件 4.1 视图容器 4.1.1 v…

RabbitMQ入门详解

前言 本篇文章将详细介绍rabbitmq的基本概念知识&#xff0c;以及rabbitmq各个工作模式在springboot中如何使用。 文章目录 介绍 简介 RabbitMQ 核心 生产者与消费者 Exchange Queue 工作模式 简单模式 工作队列模式 发布订阅模式 路由模式 主题模式 SpringBoot中…

扭蛋机潮玩小程序搭建,扭蛋机行业的创新

在当下潮玩市场中&#xff0c;扭蛋机具有盲盒的未知性和惊喜体验感&#xff0c;商品丰富&#xff0c;并且价格相对低廉&#xff0c;获得了极高的人气。年轻人开始对扭蛋机逐渐“上头”&#xff0c;为了扭到喜欢的商品不断地进行复购下单&#xff0c;在这场随机性的扭蛋游戏中&a…

【故障排查】Docker启动Nacos报错:No DataSource set 问题解决

Nacos报错内容 Nacos Server did not start because dumpservice bean construction failure : No DataSource set原因分析 Nacos 配置的是单机模式&#xff0c;使用mysql 进行存储配置文件&#xff0c;Nacos的启动脚本已经配置了MySQL的连接方式&#xff0c;根据错误提示&a…

Window下安装Zookeeper

一、下载 地址&#xff1a;https://archive.apache.org/dist/zookeeper/zookeeper-3.5.6/ 解压&#xff1a;非中文、没有空格目录下 新建data目录&#xff0c;用于存放数据文件 二、配置 进入conf目录&#xff0c;复制zoo_sample.cfg 为zoo.cfg 打开zoo.cfg 修改dataDir&…

江苏科技大学24计算机考研数据速览,有专硕复试线大幅下降67分!

江苏科技大学&#xff08;Jiangsu University of Science and Technology&#xff09;&#xff0c;坐落在江苏省镇江市&#xff0c;是江苏省重点建设高校&#xff0c;江苏省人民政府与中国船舶集团有限公司共建高校&#xff0c;国家国防科技工业局与江苏省人民政府共建高校 &am…

层次分析模型

一、算法简介 决策问题&#xff1a;面临多种方案&#xff0c;需要根据一定的标准选择某一种方案 归一化处理(让指标在同一数量级&#xff0c;且保证在同一指标下其差距不变)&#xff1a; 给指标加上权重&#xff08;加权&#xff09; 科学地设定权重&#xff1f; 二、python…

2. 深度学习的项目流程(批量化打包数据、构建模型、训练模型、波士顿房价预测、激活函数、多层感知机)

深度学习流程 1. 深度学习基本流程1.1 流程图1.2 代码实现1.3 基本概念 2. 深度学习项目流程2.1 批量化打包数据2.2 构建模型2.3 训练模型&#xff08;1&#xff09;筹备训练&#xff08;2&#xff09;开始训练 2.4 模型推理 3. 深度学习实现波士顿房价预测3.1 数据读取、切分、…

数据库之PHP联动

目录 一、软件安装 二、软件讲解 三、搭配环境 四、编辑软件配置 五、成果展示 如果有人问&#xff1a;为什么非要用xampp、VS code编辑软件?不用phpstudy等其他工具。 那么我只想说&#xff1a;因为xampp、VS code编辑软件免费(ಡωಡ)hiahiahia 一、软件安装 下载连…

Java语言程序设计基础篇_编程练习题**15.19 (游戏:手眼协调)

**15.19 (游戏:手眼协调) 请编写一个程序&#xff0c;显示一个半径为10像素的实心圆&#xff0c;该圆放置在面板上的随机位置&#xff0c;并填充随机的顔色&#xff0c;如图15-29b所示。单击这个圆时&#xff0c;它会消失&#xff0c;然后在另一个随机的位置显示新的随机颜色的…

Python task

任务1 实现wordcount&#xff1a; 代码如下&#xff1a; import re def wordcount(text):#全部小写text text.lower()text re.sub(r[^\w\s], , text)#切分words text.split()#计算频率word_count {}for word in words:if word in word_count:word_count[word] 1else:wo…

MPI框架以及PIPE数据流向细节

一、海思MPP内部处理流程图 各模块功能介绍&#xff1a; &#xff08;1&#xff09;VI:捕获视频图像&#xff0c;可对其做剪切、缩放、镜像等处理&#xff0c;并输出多路不同分辨率的图像数据. &#xff08;2&#xff09;AI:捕获⾳频数据&#xff0c;然后AENC 模块⽀持按多种⾳…

华盈生物-小分子靶点筛选服务:助力药物发现的利器

在药物发现的过程中&#xff0c;确定小分子化合物的靶点是至关重要的一步。华盈生物为科学家们提供了两种高效的小分子靶点筛选方案&#xff0c;助力研究人员精准锁定靶点&#xff0c;加速新药研发进程。 方案一&#xff1a;荧光标记与HuProt人类蛋白质组芯片结合 华盈生物的H…

lua 游戏架构 之 游戏 AI (三)ai_attack

这段Lua脚本定义了一个名为 ai_attack 的类&#xff0c;继承自 ai_base 类。 lua 游戏架构 之 游戏 AI &#xff08;一&#xff09;ai_base-CSDN博客文章浏览阅读119次。定义了一套接口和属性&#xff0c;可以基于这个基础类派生出具有特定行为的AI组件。例如&#xff0c;可以…