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

news2024/9/21 11:13:05

找到所有数组中消失的数字(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.获得元素的index
        int 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.coloradmin.cn/o/1947300.html

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

相关文章

华为OD机试 - 二叉树计算(Java JS Python C C++)

题目描述 给出一个二叉树如下图所示: 请由该二叉树生成一个新的二叉树,它满足其树中的每个节点将包含原始树中的左子树和右子树的和。 左子树表示该节点左侧叶子节点为根节点的一颗新树;右子树表示该节点右侧叶子节点为根节点的一颗新树。 输入描述 2行整数,第1行表示二叉…

MySQL数据库-备份恢复

一、MySQL日志管理 1.为什么需要日志 用于排错用来做数据分析了解程序的运行情况&#xff0c;了解MySQL的性能 2.日志作用 在数据库保存数据时&#xff0c;有时候不可避免会出现数据丢失或者被破坏&#xff0c;这样情况下&#xff0c;就必须保证数据的安全性和完整性&#…

Spring AI (五) Message 消息

5.Message 消息 在Spring AI提供的接口中&#xff0c;每条信息的角色总共分为三类&#xff1a; SystemMessage&#xff1a;系统限制信息&#xff0c;这种信息在对话中的权重很大&#xff0c;AI会优先依据SystemMessage里的内容进行回复&#xff1b; UserMessage&#xff1a;用…

c++笔记4

目录 深度优先搜索DFS DFS的复杂度 DFS与递归 递归与暴力枚举 递归树 DFS与栈 DFS的搜索剪枝 搜索剪枝与优化 可行性剪枝 最优化剪枝 减少等效的分支 优化搜索顺序 搜索的记忆化 搜索的复杂度 大多时候&#xff0c;搜索的复杂度都是指数级的。各种剪枝方案&#…

RK3568笔记四十三:MPU6050驱动开发(硬件I2C_3)

若该文为原创文章&#xff0c;转载请注明原文出处。 正点原子提供的I2C有测试ap3216c&#xff0c;SH3001等传感器&#xff0c;根据手册操作可以实现效果。 这里记录使用I2C3驱动MPU6050. 记录原因是前面有模拟I2C&#xff0c;但硬件如何使用&#xff0c;有点不是很清楚&#…

[C++] string管理:深浅拷贝写时拷贝

文章目录 拷贝问题的引入问题代码string类的构造函数String 类的析构函数测试入口函数&#xff08;问题&#xff09;详细分析 浅拷贝深拷贝传统版与现代版的String类传统String类现代版String类 写时拷贝先构造的对象后析构的影响写时拷贝举例及测试样例代码举例测试用例 拷贝问…

BGP之选路MED

原理概述 当一台BGP路由器中存在多条去往同一目标网络的BGP路由时&#xff0c;BGP协议会对这些BGP路由的属性进行比较&#xff0c;以确定去往该目标网络的最优BGP路由。BGP路由属性的比较顺序为Preferred Value属性、Local Preference属性、路由生成方式、AS_Path属性、Origin属…

react中路由跳转以及路由传参

一、路由跳转 1.安装插件 npm install react-router-dom 2.路由配置 路由配置&#xff1a;react中简单的配置路由-CSDN博客 3.实现代码 // src/page/index/index.js// 引入 import { Link, useNavigate } from "react-router-dom";function IndexPage() {const …

大数据之Oracle同步Doris数据不一致问题

数据同步架构如下&#xff1a; 出现的问题&#xff1a; doris中的数据条数 源库中的数据条数 总数完全不一致。 出现问题的原因&#xff1a; 在Dinky中建立表结构时&#xff0c;缺少对主键属性的限制 primary key(ID) not enforced 加上如上语句&#xff0c;数据条数解决一致 …

WPF+Mvvm项目入门完整教程-仓储管理系统(二)

目录 一、搭建一个主界面框架二、实现步骤1.主界面区域划分2.主界面区域实现 一、搭建一个主界面框架 主要实现主界面的框架样式和基础功能。这里特别说明一下&#xff0c;由于MvvmLight 已经过时不在维护&#xff0c;本项目决定将MvvmLight框架变更为 CommunityToolkit.Mvvm …

标题:探索pdf2image:将PDF文档转化为图像的Python魔法

标题&#xff1a;探索pdf2image&#xff1a;将PDF文档转化为图 像的Python魔法 背景 在数字时代&#xff0c;我们经常需要处理各种格式的文档&#xff0c;尤其是PDF文件。PDF以其跨平台的可读性和稳定性而广受欢迎。然而&#xff0c;有时我们需要将PDF文件转换成图像格式&am…

Golang | Leetcode Golang题解之第282题给表达式添加运算符

题目&#xff1a; 题解&#xff1a; func addOperators(num string, target int) (ans []string) {n : len(num)var backtrack func(expr []byte, i, res, mul int)backtrack func(expr []byte, i, res, mul int) {if i n {if res target {ans append(ans, string(expr))}…

Linux--Socket编程预备

目录 1. 理解源 IP 地址和目的 IP 地址 2.端口号 2.1端口号(port)是传输层协议的内容 2.2端口号范围划分 2.3理解 "端口号" 和 "进程 ID" 2.4理解 socket 3.传输层的典型代表 3.1认识 TCP 协议 3.2认识 UDP 协议 4. 网络字节序 5. socket 编程接…

【数据结构】--- 栈和队列

前言 前面学习了数据结构的顺序表、单链表、双向循环链表这些结构&#xff1b;现在就来学习栈和队列&#xff0c;这里可以简单的说栈和队列是具有特殊化的线性表 一、栈 1.1、栈的概念和结构 栈是一种遵循先入后出逻辑的线性数据结构。 栈是一种特殊的线性表&#xff0c;它只允…

矿场运输车4G视频监控管理解决方案

一、背景介绍 随着科技的不断进步和智能化时代的来临&#xff0c;矿业运输行业也在寻求更高效率与安全的管理手段。矿场运输车4G视频监控管理解决方案是一种基于4G网络技术的视频监控系统&#xff0c;专门用于监测和管理矿场内运输车辆的工作状态和安全情况。该方案为矿场运输…

【linux】在多核CPU下,好像看到不同进程在不同CPU调度

在2353这行打印的情况来看&#xff0c;操作系统好像给不同的进程分配不同的CPU&#xff0c;从上图来看&#xff0c;同一个进程好像基本使用的相同的CPU&#xff1a; 其实摸索syscall文件系统操作&#xff0c;本意是想找到内核文件系统中文件的创建&#xff0c;写入&#xff0c;…

C 观察者模式 Demo

目录 一、基础描述 二、Demo 最近需要接触到 MySQL 半同步插件&#xff0c;发现其中用到了观察者模式&#xff0c;之前没在 C 中用过&#xff0c;遂好奇心驱使下找了找资料&#xff0c;并写了个 Demo。 一、基础描述 观察者设计模式&#xff08;Observer Pattern&#xff0…

ts踩坑!使用可选链 ?.处理可能遇到的 undefined 或 null 值的情况,但是仍然收到一个关于可能为 undefined 的警告!

在 TypeScript 中&#xff0c;当你使用可选链&#xff08;Optional Chaining&#xff09;?. 时&#xff0c;你其实已经处理了可能遇到的 undefined 或 null 值的情况。但是&#xff0c;如果你仍然收到一个关于可能为 undefined 的警告&#xff0c;这可能是因为 TypeScript 的类…

Mybatis——快速入门

介绍 MyBatis是一款优秀的持久层&#xff08;Dao层&#xff09;框架&#xff0c;用于简化JDBC的开发。MyBatis 底层是基于 JDBC 实现的&#xff0c;它封装了 JDBC 的大部分功能&#xff0c;使得数据库操作更加便捷和高效。同时&#xff0c;MyBatis 也保留了 JDBC 的灵活性&…

unity2D游戏开发03状态控制

多态和动画 建立player-idle动画&#xff0c;取玩家最后两个图片 选中playcontroller控制器 将玩家动画拖进去 右键player-idle,选择set as layer Default state 右键点击Any State ,点击Make Transition 结果 动画参数 动画参数是动画控制器定义的变量&#xff0c;点击Param…