顺序表、链表刷题指南(力扣OJ)

目录

前言

题目一:删除有序数组中的重复项

思路:

题解:

题目二:合并两个有序数组

思路:

分析:

题解:

题目三:反转链表

思路:

分析:

题解:

 题目四:移除链表元素

思路一:

分析:

题解:

思路二:

分析:

题解:

总结


前言

        无论是面试准备还是日常编码实践,解决与顺序表和链表相关的算法问题都是不可避免的挑战,本篇文章旨在帮助你巩固和提升这两个重要数据结构的理解和应用能力。


题目一:删除有序数组中的重复项

 题目描述:

 示例与提示:

 思路:

         题目中的数组是一个升序的数组,依据这个点,我们可以知道,相同的元素都是紧挨着的,那要想保持升序,后一个元素一定比不等于当前元素,且比当前元素大。和前边删除元素的思路类似。

题解:

int removeDuplicates(int* nums, int numsSize){
int pos=0;int src=0;while(src<numsSize-1){if(nums[src]!=nums[src+1]){nums[pos++]=nums[src++];}elsesrc++;}nums[pos++]=nums[src];//为了防止数组越界访问,导致最后一个元素没有进行赋值,最后在这里补上return pos;
}

 

 

题目二:合并两个有序数组

 题目描述:

 示例与提示:

         合并两个有序数组的思想叫做归并,这种思路在后续的学习中也会经常遇到。有的同学可能会有这样的思路,将两个元素合并,然后qsort排序一下,这样暴力求解。这样解题也可以,但我们学习了空间复杂度和时间复杂度,就要考虑到复杂度问题,以写出好的程序。

 思路:

         注意:题目中给的是非递减排列的整数数组,举个例子:1,3,4,5,7。这样的数组属于递增数组,1,2,3,3,3,5,6。这样的数组属于非递减数组。

         了解清楚题意后,我们介绍一下解题思路,我们可以依次比较两数组中的元素,然后把小的尾插到新数组,这个就是归并的思想。但是这道题目有点不一样,它的第一个数组会很大,是两个数组有效数据个数的和,这里就要求我们把数据归并到第一个数组。

那这道题应该怎么解决呢?

        前边介绍的归并思想,我们是正着比较,然后尾插,那这道题,我们是不是可以倒着比较,然后尾插到第一个数组。

 分析:

        理解了解题的思路后,我们在进行更深一步的分析,由于力扣的题目大都是接口型题目,在调试时会很麻烦,这就是我们刷不动题的原因之一,做好全面的分析才能更高效的解决问题

 情况一:

 

 从末尾开始,依次比较,较大的数字插入到数组一的末尾:

 

 依次比较,并进行插入。

 情况二:

         两个数组依然是末尾数据进行比较,然后尾插到数组一,但是这次不同的是,数组一遍历完后,还并没有结束,此时的数据如下:

         这里就需要再将数组二剩下的数据继续插入到数组一当中。

 题解:

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

 

 

         使用3个变量,依次存储第一个数组的有效数据的末尾,第二个数组的末尾,以及第一个数组的末尾。谁大就把他插入到nums1的末尾,最后如果第二个数组没有遍历完,就将剩余数据依次插入到nums1中。

题目三:反转链表

 题目描述:

 思路:

         数组的反转很简单,最后一个元素和第一个元素交换,然后一个往前,一个往后循环遍历,但这个是单链表,没法向前遍历。那要怎么解决呢?我们可以这样做,遍历这个链表,将每个节点依次改为指向前一个节点,但要确保后续节点不丢失。这里我们就可以创建3个结构体指针,一个指向NULL,一个指向第一个节点,最后指向第二个节点,以便于记录链表后续节点。

分析:

        假设初始是这样的一个链表:

         创建3跟结构体指针,改变节点指向后,向后遍历:

         有人疑惑,链表不是不可以向前遍历吗?那n1怎么到n2的位置?我们可以直接把n2赋值给n1,然后把n3赋值给n2,n3通过指针继续向后遍历。

 当n2为NULL时就结束。

 题解:

 分析之后,我们就进行具体实现:

struct ListNode* reverseList(struct ListNode* head)
{struct ListNode* n1,*n2,*n3;n1=NULL;n2=head;if(n2!=NULL)n3=n2->next;while(n2){n2->next=n1;n1=n2;n2=n3;if(n3!=NULL)n3=n3->next;}return n1;
}

 需要注意的是空指针问题,当n3为空时就不要继续向后遍历了。

 

 题目四:移除链表元素

 题目描述:

 思路一:

        这里的思路中规中矩,遍历这个链表,与遇到要删除的val值就删除,但这里需要注意一点特殊情况,尽可能的去多虑特殊情况。

 分析:

         假设初始时给这样一个链表,要删除的是6.

         但是单一的使用指针找到了val的节点,又没法删,需要知道前一个节点。那可不可以使用替换法,把4替换到6节点的位置,遇到val值节点就把后一个节点替换过来,这样就不用使用两个指针了,但如果要删除的节点是尾节点呢?它可没有后一个节点。所以我们还是使用传统的方法。创建一个指针记录前一个节点。

         把val值前一个节点next改为val后一个节点的地址,释放掉cur指向的节点。如果删除节点是最后一个,将prev指向节点的next置为NULL。

         那这种情况呢?如果要删除的节点是头,prev就行不通了。所有我们还需要再多考虑一下头节的情况,进行特殊处理。

        初始情况下cur和head都指向头节点,把cur的下一个节点赋值为head,然后释放掉cur指向的第一个节点,再把新的头head赋给cur。这样就可以解决了。

题解:

        分析完整体思路后,我们进行代码实现,代码如下:

struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* prev=NULL;struct ListNode* cur=head;while(cur){if(cur->val==val){if(cur==head){head=cur->next;free(cur);cur=head;}else{prev->next= cur->next;free(cur);cur=prev->next;}}else{prev=cur;cur=cur->next;}}return head;
}

 思路二:

        除了传统的方法,还有另外一种方法——尾插法。遍历原链表,如果不是val就尾插到新链表。

分析:

        可以先创建一个新的链表头,初始时链表头为空,然后依次尾插,插入节点。

         这种方法更加简单快捷,没有那么多需要考虑的特殊情况,最后返回新的头。

题解:

        这种方法思路虽然很简单,但在实现时有很多需要注意的点:

struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* cur=head;struct ListNode* newhead=NULL,*tail=NULL;while(cur){if(cur->val==val){struct ListNode* del=cur;cur=cur->next;free(del);}else {if(tail==NULL)//考虑初始时头和尾都为NULL的情况{tail=newhead=cur;}else{tail->next=cur;tail=tail->next;}cur=cur->next;}}if(tail)tail->next=NULL;//遍历完之后需要将尾节点next置为NULL,此外还需要注意tail是否为NULL。return newhead;
}

         在刷题时我们会发现,很多的操作都是基于我们前边学习的单链表中基本操作的变形,此外解题的思路在很多情况下都是通用的,只需略微变形就可解决问题。所有一定要学会举一反三。

 


 

总结

        刷题不仅是为了应对面试和编码实践,更是为了培养自己的问题解决能力和学习能力。无论是顺序表还是链表,它们都是构建更复杂数据结构的基石,掌握它们对你的编程之路至关重要。最后,感谢阅读!

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

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

相关文章

springboot自定义错误消息

为了提供自定义错误消息提示&#xff0c;springboot在resources目录下&#xff0c;有一个文件ValidationMessages.properties 用于存储 验证错误的消息提示&#xff1a; 比如&#xff1a; 这样一个ValidationMessage.properties username.notempty用户名不能为空 username.len…

如何压缩高清PDF文件大小?将PDF文件压缩到最小的三个方法

PDF格式是一种非常常用的文档格式&#xff0c;但是有时候我们需要将PDF文件压缩为更小的大小以便于传输和存储。在本文中&#xff0c;我们将介绍三种PDF压缩的方法&#xff0c;包括在线PDF压缩、利用软件PDF压缩以及使用WPS缩小pdf。 首先&#xff0c;在线PDF压缩是最常用的方…

华云安参编的《云原生安全配置基线规范》正式发布

由中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;、中国通信标准化协会主办的第十届可信云大会云原生安全分论坛于7月26日在北京国际会议中心成功召开。作为大会上展示的成果之一&#xff0c;由中国信通院联合行业领先企业共同编写的《云原生安全配置基线规…

寒假作业(蓝桥杯2016年省赛C++A组第6题 )

题目&#xff1a; 注&#xff1a;蓝桥杯2016年省赛CA组第6题 请填写表示方案数目的整数。 题解&#xff1a; 由题可知这是一道全排列问题&#xff0c;因此我们可以使用c的next_permutation函数对于1-13的数字进行全排列即可&#xff0c;并每次排列判断是否满足题意。 注意…

无边界野望:高通也有痛点?

外界给予高通的称呼无非是性价屠夫&#xff0c;因为即可“拳打”联发科&#xff0c;又能四度包下上海ChinaJoy展馆做游戏技术支持的王者&#xff0c;对高通来说它的路是无边界的&#xff0c;也是跨界之路上前行的“诗和远方”。 这里&#xff0c;既有生成式AI在终端侧布局、与…

React之组件的生命周期

React之组件的生命周期 一、概述二、整体说明三、挂载阶段四、更新阶段五、卸载阶段 一、概述 生命周期:一个事务从创建到最后消亡经历的整个过程组件的生命周期&#xff1a;组件从被创建到挂载到页面中运行&#xff0c;再到组件不用时卸载的过程意义&#xff1a;理解组件的生…

使用IPSEC VPN 在有防火墙的场景和有NAT转换的场景下实现隧道通信实验

目录 一、在有防火墙的场景 1、为所有设备配置对应ip地址&#xff1a; 2、进入两个防火墙实现公网互通 3、测试公网是否互通 4、进入SW1配置IPSEC VPN 5、进入SW2配置IPSEC VPN 6、配置策略方向ESP的流量 7、尝试使用PC1访问PC2 二、在有NAT地址转换的场景 1、为新增加…

视频号将不支持添加企业微信:私域流量受阻

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 以前大家一直嚷嚷着说微信视频号企业微信私域流量神器&#xff0c;这下好了&#xff0c;从今日起这个功能没了&#xff0c;以后新的视频号不能绑定企业微信了&#xff0c;但老视频号还可以。 昨天…

招投标系统简介 招投标系统源码 java招投标系统 招投标系统功能设计

&#xfeff;功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&…

【数据结构】二叉树、二叉搜索树、平衡二叉树、红黑树、B树、B+树

概述 二叉树&#xff08;Binary Tree&#xff09;&#xff1a;每个节点最多有两个子节点&#xff08;左子节点和右子节点&#xff09;&#xff0c;没有限制节点的顺序。特点是简单直观&#xff0c;易于实现&#xff0c;但查找效率较低。 二叉搜索树&#xff08;Binary Search…

烘焙小程序蛋糕店烘焙店源码点心店小程序源码

本系统开发使用JAVA技术栈开发 使用uniapp技术栈 支持微信小程序 &#xff0c;对接打印机&#xff0c;对接第三方同城跑腿平台 用户端使用&#xff1a;uniapp 管理端使用&#xff1a;vueelementui 后台服务使用&#xff1a;springbootjpa

Java版本工程行业管理系统源码-专业的工程管理软件-提供一站式服务 em

​ 工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…

不同语言操作符的优先级

看到标题&#xff0c;可能会心生疑惑: 这么基础且重要的操作&#xff0c;不同语言不应该是一致的吗&#xff1f; 并不一定&#xff0c;比如对于右移运算和加法运算&#xff0c;Go就与其他多数语言表现得不一致&#xff1a; Go: package mainimport "fmt"func main() …

Vault数据备份恢复-MySQL

前言 Vault提供了可靠的功能来保护数据库和其他关键数据。 对于MySQL数据库,Vault提供了一个易于使用的解决方案,可以自动创建和管理定期备份,并支持从备份中快速恢复数据。本文将介绍Vault后端存储MySQL的备份恢复,包括如何设置Vault、如何进行数据备份和还原、如何保护…

iOS——Block two

Block 的实质究竟是什么呢&#xff1f;类型&#xff1f;变量&#xff1f;还是什么黑科技&#xff1f; Blocks 是 带有局部变量的匿名函数 Blocks 由 OC 转 C 源码方法 在项目中添加 blocks.m 文件&#xff0c;并写好 block 的相关代码。打开「终端」&#xff0c;执行 cd XX…

[C++]01.基础,数据类型,运算符

01.基础,数据类型,运算符 一.C基础入门1.HelloWorld2.注释3.变量4.常量5.关键字6.命名规则 二.数据类型1.整形2.sizeof关键字3.浮点型4.字符型5.转义字符6.字符串型7.布尔类型8.数据的输入 三.运算符1.算数运算符2.赋值运算符3.比较运算符4.逻辑运算符 一.C基础入门 1.HelloWo…

webshell详解

Webshell详解 一、 Webshell 介绍二 、 基础常见webshell案例 一、 Webshell 介绍 概念 webshell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境&#xff0c;也可以将其称做为一种网页后门。黑客在入侵了一个网站后&#xff0c;通常会将asp或php后门文件与…

【普通人维护windows的方法,不中毒,不弹窗,不卡顿】

前言 IT人也是普通人&#xff0c;我就说说普通人维护电脑的方法。 我的电脑配置 给大家看看&#xff0c;配置一般&#xff0c;运行软件和游戏&#xff0c;可以保持基本流程 日常维护措施 我不太喜欢设定一些非主流的配置&#xff0c;下了一个360卫士,360其他的套餐可以不用下…

数据结构——绪论

一、绪论 &#xff08;一&#xff09;基本概念 数据&#xff1a;数据是对客观事物的符号表示&#xff0c;在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。 数据元素&#xff1a;数据元素是数据的基本单位&#xff0c;在计算机程序中通常作为一个整…

js实现按照句号将一段文本进行分段

/*** 将给定的文本按照300字并且按照句号分为多个p标签** param text 给定的文本* returns 返回分割后的多个p标签的数组*/ function splitTextByParagraph(text) {// 将文本按照句号分割成多个句子const sentences text.split(。);// 初始化一个空数组来存储生成的p标签const…