面试题 消失的两个数字
本题目来源是面试题 17.19. 消失的两个数字 - 力扣(LeetCode)
这道题也是消失的数字升级版面试题 17.04. 消失的数字 - 力扣(LeetCode)
这道题也是在鹏哥C语言和航哥数据结构中都重点讲解的题目,当时只是大概一听,听会了而已,也没有实践,借着这次机会好好会会这个老友,发现真不太一般,感觉就是脑子好痒,要长脑子了~
题面:
给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?
以任意顺序返回这两个数字均可。
示例 1:
输入: [1]
输出: [2,3]
示例 2:
输入: [2,3]
输出: [1,4]
提示:
nums.length <= 30000
答案格式:
int* missingTwo(int* nums, int numsSize, int* returnSize)
{
}
分析过程
首先读懂题目:
有这么一个数组,范围是从1到N,从1开始,记好这一点,至于N是几?看第二个参数去
时间复杂度是O(N),空间复杂度是O(1),复杂度还不懂的看这篇文章去一篇文章读懂时间复杂度和空间复杂度-CSDN博客
然后是参数分析:
- 给定了一个数组指针nums,这是一个缺俩数的数组的指针(缺大德的数组,干啥非缺俩数)
- numsSize是nums指向的数组的大小,也就是N - 2 = numsSize
- returnSize是告诉程序缺了几个数,明显就是2个啊,题目都说了
上面这三点参数分析完之后才能好好做题
还有,这是OJ在线答题的较常见的接口型的题,这一点很重要,因为这决定了你提交答案的方式,不知道什么是接口型题的去看这篇文章一篇文章读懂时间复杂度和空间复杂度-CSDN博客,文章的最后有OJ测试题目的种类解读
方法一(纯暴力):
既然知道了数组的大小就是1到numsSize+2,最大范围是30000,直接创建一个大小是30000的int类型的数组arr
然后是用一个while循环每读取一个数,直接在arr[*nums]++,把对应的位置置成1,循环条件是循环次数小于numsSize,最后再遍历一次arr数组,从1到numsSize+2,为什么是加2?因为给你的数组缺俩数啊。
遍历的时候,再设俩值ab,用于存储缺少的数字。
在这个题目中有个比较坑的一点,它让你返回的是int类型的指针,还让你一次性返回俩数,众所周知,return只能返回一个值,所以这俩数ab只能扔到一个数组里面去,再把这个数组名传过去,这里的数组名代表首元素地址,应该不会不知道吧,不知道也没关系,看这篇文章就能搞懂了一篇文章搞懂指针和指针运算(指针初阶)-CSDN博客
到这里,你已经完成了这道题95%的答题了,最最最重要的地方来了,有点烫嘴,不要介意
学过动态内存函数的人可以直接看,没学过的建议先看看动态内存函数都是干啥的,先了解一下也行,如何了解?当然也是看我写的文章了一篇文章搞定动态内存函数-CSDN博客
学过的人看过来!刚看完文章的人也看过来!没看过的,没学过的先去看文章!
这个题,是接口型的题,也就是不会保存数据,服务器在用完你写的这个函数后,需要在服务器里面得到答案,因此,不能直接输出答案,而且也不能用变量储存,也不能用数组储存结果,因为在程序出了函数的时候,这个函数的一切变量都被释放了,那么只能用malloc函数去服务器申请一块内存存放得到的这两个数。也就是申请两个int类型大小的空间,把bc放进去就完了
好了分析到这里吧。
经过测试,发现还没全对,44个样例只通过了38组,不知道这种暴力的方式,哪里欠考虑了,有读者找了,可以@我一下
上代码:
int* missingTwo(int* nums, int numsSize, int* returnSize)
{
int i = 0;
int num[2] = {
0 };
int arr[30000] = {
0 };
int a = 0;
for (i = 0; i < numsSize; i++)
{
arr[*(nums + i)] = 1;
}
for (i = 1; i < numsSize + 3; i++)
{
if (arr[i] == 0)
{
num[a] =