iOS object-C 解答算法:找到所有数组中消失的数字(leetCode-448)

ops/2024/10/11 0:21:42/

找到所有数组中消失的数字(leetCode-448)

题目如下图:(也可以到leetCode上看完整题目,题号448)

光看题看可能有点难以理解,我们结合示例1来理解一下这道题.

有8个整数的数组 nums = [4,3,2,7,8,2,3,1], 求在闭区间[1,8]范围内(即1,2,3,4,5,6,7,8)的数字,哪几个没有出现在数组 nums 中. 

我们很容易一看就看出,5和6没有出现在数组nums中.

还是拿示例1来说,如果可以用新建一个数组newNums = [1,2,3,4,5,6,7,8] 与 原数组nums = [4,3,2,7,8,2,3,1] 比较,立马可以找到缺少了元素5和6,但是题目要求不得使用额外空间.所以只能在原数组上操作.

解法一:

我们先来说一下常规解法(就是可以使用额外空间的解法). 遍历nums数组,把遍历到的元素一一在newNums数组里删除,剩下没删除的元素就是nunms没有的.

代码如下:

- (void)viewDidLoad 
{[super viewDidLoad];NSMutableArray * originalArray = [[NSMutableArray alloc]initWithObjects:@"4",@"3",@"2",@"7",@"8",@"2",@"3",@"1", nil];NSMutableArray * newArray = [[NSMutableArray alloc]init];for (int i = 1; i < originalArray.count + 1; i ++){[newArray addObject:[NSString stringWithFormat:@"%d",i]];}NSMutableArray * array2 = [self missNum:originalArray NewArray:newArray];NSLog(@"array2==%@",array2);
}- (NSMutableArray *)missNum:(NSMutableArray *)originalArray NewArray:(NSMutableArray *)newArray
{for (int i = 0 ; i < originalArray.count; i ++){NSString * oValue = originalArray[i];[newArray removeObject:oValue];}return newArray;
}

以上就是我们通常想到的常规解法,时间复杂度为O(n^2),空间复杂度为O(n). 

时间复杂度不符合题目要求的O(n), 题目还说了不占用额外空间(返回函数不算),这一点我不太懂,这一道题我开辟了很多空间,除了不算的返回函数newArray,还有int i, NSString * oValue, 这个算不算额外空间,如果有懂的小伙伴评论区帮我解答一下.

但是通常都是用空间换时间,所以这么写现实中问题不大.

解法二:

我们可以把 数组nums = [4,3,2,7,8,2,3,1] 看做是 数组newNums = [1,2,3,4,5,6,7,8],减去几个数,再增加几个相同的数(例如这里增加了2和3),再打乱它们的排列组合. 注意:nums和newNums的元素个数(就是count一定是相等的,这是题目隐含的意思).

所以在nums 里的index=0的元素4, 它原来的index应该为3. 我们就按照这个逻辑,把nums里所有元素的的原index都找到,那么剩下的没有找到的index,就是没有出现在nums 里的元素.

思路如下:

nums元素 4---->index = 3

nums元素 3---->index = 2

nums元素 2---->index = 1

nums元素 7---->index = 6

nums元素 8---->index = 7

nums元素 2---->index = 1

nums元素 3---->index = 2

nums元素 1---->index = 0

通过上面列出的思路,我们可以看到,index=4和index=5 没有出现,所以没有出现的数字为 5 和 6.

因为不能额外增加空间,所以我们不能新创建一个数组和存放index.那么我们只能使用标记法-->在原数组标记.

标记的方法有很多种,例如可以在数组前加个减号(-)标记, 也可以每个元素加上n标记(例如4+8),也可以使用符号标志(例如*,但是这道题是数字,明显不能用这个方法).

我们这里就使用减号标志号了

nums元素 4 ---> index = 3 ,在数组nums index=3的位置加个减号:nums = [4,3,2,-7,8,2,3,1];

nums元素 3 ---> index = 2 ,在数组nums index=2的位置加个减号:nums = [4,3,-2,-7,8,2,3,1];

nums元素 2 ---> index = 1 ,在数组nums index=1的位置加个减号:nums = [4,-3,-2,-7,8,2,3,1];

我们下一步按理说是要取元素7的,但是nums里7 已经变成-7了,所以我们为了不受标记影响,我们每次都取元素的绝对值(object-c取数字绝对值的方法为abs())

nums元素 7 ---> index = 6 ,在数组nums index=6的位置加个减号:nums = [4,-3,-2,-7,8,2,-3,1];

nums元素 8 ---> index = 7 ,在数组nums index=7的位置加个减号:nums = [4,-3,-2,-7,8,2,-3,-1];

下一步的元素2.index=1 的位置已经标记了减号,所以我么标记之前先判断待标记的位置是否为负数,如果为负数,则无需重复标记

nums元素 2 ---> index = 1 ,无需重复标记

nums元素 3 ---> index = 2 ,无需重复标记

nums元素 1 ---> index = 0,在数组nums index=0的位置加个减号:nums = [-4,-3,-2,-7,8,2,-3,-1];

经过一个for循环的标记,我们就找出数组里为正数数的index,即得到没有出现的数字

代码如下:

- (NSMutableArray *)missNum2:(NSMutableArray *)originalArray
{for (int i = 0 ; i < originalArray.count; i ++){//1.取值要取绝对值 abs()int value = abs([originalArray[i] intValue]);//2.获得元素的indexint index = value - 1;//3.标记index//3.1.标记之前要判断index的元素是否为负数,如果为负数,则说明已经标记过了,无需标记if (originalArray[index] > 0){originalArray[index] = [NSString stringWithFormat:@"-%@",originalArray[index]];}NSLog(@"originalArray==%@",originalArray);}NSMutableArray * newArray = [[NSMutableArray alloc]init];for (int i = 1; i < originalArray.count + 1; i ++){[newArray addObject:[NSString stringWithFormat:@"%d",i]];}return newArray;
}

以上代码的时间复杂度为O(n),空间复杂度也为O(n)

时间复杂度满足题目要求, 这个写法我也开辟了很多空间,除了不算的返回函数newArray,还有int value, int index , int i, 这个算不算额外空间,如果有懂的小伙伴评论区帮我解答一下.

​​​​​​​但是通常都是用空间换时间,所以这么写现实中问题不大.


http://www.ppmy.cn/ops/86948.html

相关文章

智云-一个抓取web流量的轻量级蜜罐

智云-一个抓取web流量的轻量级蜜罐 安装环境要求 apache php7.4 mysql8 github地址 https://github.com/xiaoxiaoranxxx/POT-ZHIYUN 系统演示

DiAD代码use_checkpoint

目录 1、梯度检查点理解2、 torch.utils.checkpoint.checkpoint函数 1、梯度检查点理解 梯度检查点&#xff08;Gradient Checkpointing&#xff09;是一种深度学习优化技术&#xff0c;它的目的是减少在神经网络训练过程中的内存占用。在训练深度学习模型时&#xff0c;我们需…

JAVA零基础学习3(Scanner类,字符串,StringBuilder,StringJoinder,ArrayList成员方法)

JAVA零基础学习&#xff13; Scanner类输入示例代码代码解释完整代码1. 读取字符串2. 读取整数3. 读取浮点数4. 读取布尔值5. 读取单个单词6. 读取长整型数7. 读取短整型数8. 读取字节数注意事项总结 API 字符串解释示例解释解决方法示例&#xff1a;使用 StringBuilder String…

计算机基础(day1)

1.什么是内存泄漏&#xff1f;什么是内存溢出&#xff1f;二者有什么区别&#xff1f; 2.了解的操作系统有哪些&#xff1f; Windows&#xff0c;Unix&#xff0c;Linux&#xff0c;Mac 3. 什么是局域网&#xff0c;广域网&#xff1f; 4.10M 兆宽带是什么意思&#xff1f;理论…

AI测试:人工智能模型的核心测试指标,分类判别、目标检测、图像分割、定量计算分别有哪些指标?

在前面的人工智能测试技术系列文章中&#xff0c;我们详细介绍了人工智能测试的技术方法和实践流程。在了解人工智能测试方法后&#xff0c;我们需要进一步学习和研究如何衡量这些方法的有效性&#xff0c;即人工智能模型测试指标的选择。测试指标的选择主要取决于模型的类型和…

Git操作指令(已完结)

Git操作指令 一、安装git 1、设置配置信息&#xff1a; # global全局配置 git config --global user.name "Your username" git config --global user.email "Your email"# 显示颜色 git config --global color.ui true# 配置别名&#xff0c;各种指令都…

AI绘画对话视频工具

目录 前言&#xff1a; 一、小程序部署上线的流程 二、AI系统前端uniapp功能 三、后台功能 四、后续操作 前言&#xff1a; 目前很火的AI 工具&#xff0c;对话&#xff0c;绘画&#xff0c;视频封功能都是分开几个模块&#xff0c;需要从不同的链接才能进入使用。然后工具…

Prometheus-部署

Prometheus-部署 Server端安装配置部署Node Exporters监控系统指标监控MySQL数据库监控nginx安装grafana Server端安装配置 1、上传安装包&#xff0c;并解压 cd /opt/ tar xf prometheus-2.30.3.linux-amd64.tar.gz mv prometheus-2.30.3.linux-amd64 /usr/local/prometheus…