顺序表链表OJ题(1)——【LeetCode】

W...Y的主页 😊

代码仓库分享 💕


 前言:

今天我们来回顾一下顺序表与链表,针对这一块我们也有许多OJ题目供大家参考。当我们学习完顺序表链表后避免不了一些习题的练习,这样才能巩固我们学习的内容。

话不多说,我们开始进入OJ习题训练!!!

【leetcode 27.移除元素】 

OJ链接

给你一个数组 和一个值 ,你需要原地移除所有数值等于 的元素,并返回移除后数组的新长度。numsvalval

不要使用额外的数组空间,你必须仅使用 额外空间并原地修改输入数组O(1)

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

题目函数接口 nums:给定数组内容。numsSize:数组长度大小。val:移除元素。


题目要求原地删除数据,不能创建任何数组,这就会使原本简单的题变复杂。那我们应该怎么办呢?

首先我们最先想到的方法是遍历数组,遇到需要删除的内容就将数组后面的元素向前挪动一位,让其覆盖。但是这种方法非常”危险“,有可能导致数组越界,也有可能删除遗漏。所以这不是个好方法。

接下来将一个比较新颖且简单的方法:

双指针: 创建两个指针变量src与dst,两个指针全部指向数组开头。如果src指向的内容不是val,将src的内容赋值给dst,然后src与dst全部向后挪动一位。反之如果src指向的内容为val,dst保持原来的位置不动,src向后挪动一位。直至src指向数组的末尾结束。

 这个方法即保证没有创建任何数组空间复杂度为O(1),也优化了暴力遍历法中时间复杂度,从O(n^2)->O(n)。

代码展示:

nt removeElement(int* nums, int numsSize, int val){int ret = 0;int valp = 0;int n = numsSize;while(ret < numsSize){if(nums[ret] != val){nums[valp++] = nums[ret++];}elseret++;}return valp;
}

【leetcode 26.删除有序数组中的重复项】

OJ链接 

给你一个 升序排列 的数组 nums ,请你原地删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案int k = removeDuplicates(nums); // 调用assert k == expectedNums.length;
for (int i = 0; i < k; i++) {assert nums[i] == expectedNums[i];
}

如果所有断言都通过,那么您的题解将被通过

题目函数接口: nums:升序数组。numsSize:数组中元素个数。


思路:快慢双指针

分析:创建两个指针变量fast与slow

如果两个指针指向内容全部相同,fast向后挪动一位slow不变。

如果两个指针指向不同内容,先让slow向后移动一位,再将fast指向的内容赋值给slow,再将fast向后移动一位即可。

等到fast指向数组末尾时,循环结束!

代码演示: 

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

leetcode 88.合并两个有序数组】 

OJ链接

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

题目接口函数: 

nums1与nums2:两个非递减数组。nums1Size:nums1数组大小。nums2Size:nums2数组大小。m:nums1数组有效元素个数。n:nums2数组有效元素个数。


其实我们可以直接将两个数组进行归并,然后进行qsort排序直接完成。但是效率太低了,qsort函数底层原理为快速排序法,时间复杂度太高。

那有没有什么时间复杂度低的解法呢?

这道题本来可以两个数组进行比较,再开辟一个数组,两个数组元素进行比较,谁比较小就尾插到新数组中去。

但是这个题比较特殊,nums1开辟的空间比较大,可以放下两个数组的所有内容,所以我们必须将排序好的数组放入nums1中为了保证时间复杂度为O(m+n)。

但是我们可以使用这种方法的变形(三指针)。

解法:我们可以倒着比较,取大的依次从后往前插入。 创建三个指针,一个指向nums2数组末尾处,一个指向nums1有效元素末尾,还有一个指向nums1数组末尾处。

然后我们进行比较即可: 注意当end1与end2全部结束才可以结束循环,否则会有问题。

举例:num1:【5,6,7,0,0,0】,num2:【2,5,6】

 代码展示:

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

【leetcode 206.反转链表】

OJ链接

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

 题目接口函数:

head:链表头节点


我们在反转数组时,只需要两个指针一个指向头,一个指向尾进行交换即可,最后指向中间即可结束。但是单链表没有数组的特性,不能进行逆向读取,所以这个方法行不通。

现在提供两种方法:

方法一:创建3个指针n1、n2、n3分别指向NULL、head、head->next。标记好三个位置即可进行链表反转。 让n2->next指向n1,然后n1=n2、n2=n3、n3=n3->next即可

一直循环直到n3指向NULL时循环停止结束。

代码演示: 

struct ListNode* reverseList(struct ListNode* head){struct ListNode* a = NULL;struct ListNode* b = head;struct ListNode* c = NULL;if(b)c = b->next;if(head){while(c){a = b;b = c;c = b->next;b->next = a;}head->next = NULL;return b;}elsereturn head;

 我们考虑问题就必须全面,如果链表中只有一个数则返回头指针head即可。

(头插法)方法二:

创建一个新链表头newhead,将旧链表元素挨个反向插入newhead中即可。

 

上述就是操作流程图!!!

代码演示:

struct ListNode* reverseList(struct ListNode* head){ 
struct ListNode* cur = head;struct ListNode*  newhead = NULL;while(cur){struct ListNode* next = cur->next;cur->next = newhead;newhead = cur;cur = next;}return newhead;}

【leetcode 203.移除链表元素】

OJ链接

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。 

 题目接口函数:

head:链表头节点。val:删除目标数


思路分析:移除目标元素,我们就要遍历链表进行查找。创建两个指针prev与cur,prev永远指向cur前一个节点,用来记录。

当cur遇到目标数时,我们就可以使用prev->next =cur->next,将目标数删除。直至cur指向NULL结束。

整体思路如下:

 虽然看上去很简单,但是这种题的“极端”情况非常多。我们必须把这些特殊情况考虑清楚再去写程序才能保证万无一失。

如果遇到上述情况,使用prev->next =cur->next就不实用了,程序就会出错。那我们应该怎么办呢?

我们应该在使用prev->next =cur->next时就先把元素为val的干掉,让head指向不是val的元素。 下面是代码演示:

struct ListNode* removeElements(struct ListNode* head, int val){struct ListNode* prev = NULL, *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;
}

还有一种思路更清晰的方法:

创建一个新的头节点newhead,让cur遍历链表,把元素内容不是val的挪下来与newhead链接即可。

这样的思路更清晰,空间复杂度对于之前方法一没有改变,但是时间复杂度增加了。因为在newhead尾插时要找尾节点。我们可以增加一个尾指针指向newhead链表的尾节点,这样就可以优化时间复杂度。

代码演示:

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*der = cur;cur = cur->next;free(der);}else{if(tail == NULL){newhead = tail = cur;}else{tail->next = cur;tail = tail->next;}cur = cur->next;}if(tail){tail->next = NULL;}}return newhead;
}

 代码中有很多极端问题需要大家去想清楚,在这里就不过多讲述了,不懂可以私信我!!!

【leetcode 876.链表的中间节点】

OJ链接 

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

题目函数接口:

head:目标链表的头节点。


分析题目:这道题我们可以使用最原始的方法进行,先将链表遍历一遍求出链表长度,然后再次进行循环找出中间值即可。

但是有些公司面试会有题目限制要求,只让我们遍历一遍找出中间值。那我们应该怎么做呢?

(快慢指针):

我们创建两个指针变量slow与fast指向链表的头节点,slow一次只移动一个节点,而fast指针一次移动两个节点。当fast指向NULL时,我们的slow节点顺理成章的就找到了中间节点。

这种类型的题目我们就可以利用速度差来达到题目要求!

代码演示: 

struct ListNode* middleNode(struct ListNode* head){struct ListNode* fast = head;struct ListNode* slow = head;while(fast&&fast->next){fast = fast->next->next;slow = slow->next;}return slow;
}

以上是本次全部内容,有错误或不同见解的希望与博主进行沟通交流,博主会继续努力将更好的博客内容带给大家,你们的三连是对博主最大的支持!!! ❤️❤️

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

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

相关文章

Javaweb基础学习(4)

Javaweb基础学习&#xff08;4&#xff09; 一、JSP学习1.1 JSP的简介概述1.2 JSP快速入门1.3 JSP原理1.4 JSP脚本1.5 JSP缺点1.6 EL表达式1.7 JSL标签1.7.1 JSL快速入门 1.8 MVC 模式和三层架构1.9 三层架构 三、会话跟踪技术3.1 会话跟踪技术介绍3.2 Cookie的基本使用3.3、Co…

python-图片之乐-ASCII 文本图形

ASCII&#xff1a;一个简单的字符编码方案 pillow模块&#xff1a;读取图像&#xff0c;访问底层数据 numpy模块&#xff1a;计算平均值 import sys, random, argparse import numpy as np import math from PIL import Image定义灰度等级和网格 定义两种灰度等级作为全局值…

Linux环境离线安装MySQL8.0.33

目录 一、准备 1、检查libaio.so.1 2、卸载删除原有的mariadb 3、删除my.cnf 4、下载mysql安装包 二、安装 1、上传mysql 2、建立mysql所需目录 3、建立配置文件my.cnf 4、创建mysql用户并授权 5、初始化数据库 6、启动MySQL数据库 7、常见启动报错处理 8、配置M…

VMware标准虚拟交换机和分布式交换机

一、虚拟交换机 初期的网络虚拟化&#xff0c;是非常狭义的概念&#xff0c;主要指的是因为计算资源虚拟化&#xff0c;每台物理宿主机上安装了虚拟化软件&#xff0c;同时会部署了虚拟交换机&#xff0c;负责物理机上面承载的VM&#xff08;虚拟机&#xff09;之间与对外的通…

用心维护好电脑,提高学习工作效率

文章目录 一、我的电脑1.1 如何查看自己的电脑硬件信息呢&#xff1f; 二、电脑标准保养步骤和建议2.1 保持清洁2.2 定期升级系统和软件2.3 安全防护2.4 清理磁盘空间2.5 备份重要数据2.6 优化启动项2.7 散热管理2.8 硬件维护2.9 电源管理2.10 注意下载和安装2.11 定期维护 三、…

数据结构:单向循环链表

单向循环链表和单向链表差不多&#xff0c;只需要记录头节点的位置把单向链表判断NULL的地方改为判断头节点即可 dxxhlb.h dxxhlb.cmain.c 结果

聚类分析 | MATLAB实现基于AHC聚类算法可视化

聚类分析 | MATLAB实现基于AHC聚类算法可视化 目录 聚类分析 | MATLAB实现基于AHC聚类算法可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 AHC聚类算法&#xff0c;聚类结果可视化&#xff0c;MATLAB程序。 Agglomerative Hierarchical Clustering&#xff08;自底…

ArrayList与顺序表

文章目录 一. 顺序表是什么二. ArrayList是什么三. ArrayList的构造方法四. ArrayList的常见方法4.1 add()4.2 size()4.3 remove()4.4 get()4.5 set()4.6 contains()4.7 lastIndexOf()和 indexOf(&#xff09;4.8 subList()4.9 clear() 以上就是ArrayList的常见方法&#xff01…

【科研论文配图绘制】task6直方图绘制

【科研论文配图绘制】task6直方图绘制 task6 主要掌握直方图的绘制技巧&#xff0c;了解直方图含义&#xff0c;清楚统计指标的添加方式 1.直方图 直方图是一种用于表示数据分布和离散情况的统计图形&#xff0c;它的外观和柱形图相近&#xff0c;但它所 表达的含义和柱形图…

串口联网通信数据监听视监控侦测协议规约破解方案

作为物联网数据采集解决方案专业提供商,数采物联网小编daq-iot 在这里做以下内容介绍,并诚挚的欢迎大家讨论和交流。 本方案主要用于监听和侦测 串口通信数据报文&#xff0c;主要用于协议报文分析 破解领域。 例如破解摄像头控制道闸开启的命令等。 监控和分析通信数据代表的含…

设计模式-职责链模式

文章目录 职责链模式模式概述主要角色适用场景实现步骤优点注意事项 定义职责链结构示例总结 职责链模式 职责链模式是一种行为设计模式&#xff0c;它可以将请求的发送者和请求的处理者解耦&#xff0c;并按照预定义的顺序处理请求。职责链模式常用于需要逐级审批或转交处理的…

网络编程——套接字和字节序

目录 一、BSD套接字接口1.1 套接字类型1.2 套接字的位置 二、字节序2.1 大小端2.2 大小端判断2.3 主机字节序和网络字节序2.4 字节序转换函数 一、BSD套接字接口 BSD套接字接口是BSD的进程间通信的方式&#xff0c;它不仅支持各种形式的网络应用而且它还是一种进程间通信的机制…

汽车类 ±0.25°C SPI 温度传感器,TMP126EDBVRQ1、TMP126EDCKRQ1、TMP127EDBVRQ1引脚配置图

一、概述 TMP126-Q1 是一款精度为 0.25C 的数字温度传感器 &#xff0c; 支持的环境温度范围为 -55C 至 175C 。TMP126-Q1 具 有 14 位 &#xff08; 有符号 &#xff09; 温度分辨率(0.03125C/LSB)&#xff0c;并且可在 1.62V 至 5.5V 的电源电压范围内工作。TMP126-Q1 具有转…

Linux-crontab使用问题解决

添加定时进程 终端输入&#xff1a; crontab -e选择文本编辑方式&#xff0c;写入要运行的脚本&#xff0c;以及时间要求。 注意&#xff0c;如果有多个运行指令分两种情况&#xff1a; 1.多个运行指令之间没有耦合关系&#xff0c;分别独立&#xff0c;则可以直接分为两个…

SpringDataRedis 使用

1. SpringDataRedis 特点2. 使用 SpringDataRedis 步骤3. 自定义 RedisTemplate 序列化4. SpringDataRedis 操作对象 1. SpringDataRedis 特点 提供了对不同 Redis 客户端的整合&#xff08;Lettuce 和 Jedis&#xff09;提供了 RedisTemplate 统一 API 来操作 Redis支持 Redi…

【附安装包】Vm虚拟机安装Linux系统教程

软件下载 软件&#xff1a;Linux版本&#xff1a;18.0.4语言&#xff1a;简体中文大小&#xff1a;1.82G安装环境&#xff1a;VMware硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①丨百度网盘&#xff1a;1.Vm虚拟机15.5下载链接&#xff1a;https://pan…

Ansible学习笔记(一)

1.什么是Ansible 官方网站&#xff1a;https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html Ansible是一个配置管理和配置工具&#xff0c;类似于Chef&#xff0c;Puppet或Salt。这是一款很简单也很容易入门的部署工具&#xff0c;它使用SS…

【USRP】集成化仪器系列1 :信号源,基于labview实现

USRP 信号源 1、设备IP地址&#xff1a;默认为192.168.10.2&#xff0c;请勿 修改&#xff0c;运行阶段无法修改。 2、天线输出端口是TX1&#xff0c;请勿修改。 3、通道&#xff1a;0 对应RF A、1 对应 RF B&#xff0c;运行 阶段无法修改。 4、中心频率&#xff1a;当需要…

MySQL的共享锁和排他锁

锁定读 Locking Reads 有过编程语言并发学习经验的同学&#xff0c;应该都了解过读写锁的概念。读写锁主要是为了解决多读少写条件下&#xff0c;程序的并发性能问题。它的特点即是&#xff1a;如果一个线程持有了读锁&#xff0c;那么其他线程也是可以继续读取它锁定的数据&a…

CANOCO5.0实现冗余分析(RDA)最详细步骤

在地理及生态领域会常使用RDA分析&#xff0c;RDA的实现路径也有很多&#xff0c;今天介绍一下CANOCO软件的实现方法。 1.软件安装 时间调整到2010年 2.数据处理 得有不同的物种或者样点数值&#xff0c;再加上环境因子数据。 3.软件运行 4.结果解读 结果解读主要把握这几点…