leetcode之Find All Numbers Disappeared in an Array
问题来源:Find All Numbers Disappeared in an Array
很久没有刷题了,感觉大脑开始迟钝,所以决定重拾刷题的乐趣。一开始不要太难,选一些通过率高的题目做,然后就看到了这个题目。我有些吃惊,这个题我虽然知道两种解法,但本身还是有难度的,居然通过率这么高。然后就搜索相关网页,看到一个和它很接近的题目《Find All Duplicates in an Array》,然后就释然了。这两个题目有相同的题干,只是问题略微不同,解法有相似之处。估计是因为题号太接近了,会做第一个之后,第二个也很容易就做对了。本文主要解析《Find All Numbers Disappeared in an Array》,顺便简单解释一下《Find All Duplicates in an Array》。
该题的含义是:给定一个长度为n的数组,数组元素是1~n。但是有些元素出现一次,有些元素出现两次,从而也会导致有些元素不出现。现在让我们找到哪些元素没有出现。另外一个题目是让我们找到出现两次的元素。时间复杂度O(n),空间复杂度O(1)。
解法一
第一种方法是利用之前博客《数组统计分析的另一种方法》介绍的方法—元素归位法。元素归位法很容易理解,就是将n个元素交换到它应该在的位置。例如,元素5就放到位置4(下标从0开始)。这里需要注意一点,将某个元素交换到正确位置可能会导致当前位置的元素还不在正确位置,需要继续交换直到不能交换为止,伪代码如下:
for i=1:n
while canSwap(i) do swap(i);
将元素归位之后,我们就很容易获得哪些元素没有出现。当某个位置不是正确元素的时候,就意味着这个元素没有出现。也即针对没有出现的元素,我们只需要返回下标;针对出现两次的元素,我们只需要返回该位置的值。
这里有一个疑问,伪代码有两个for循环,复杂度是不是O(n2)呢?不是,复杂度还是O(n),这个可以通过均摊分析来解释:如果满足交换条件,则每次都会使一个元素处在正确位置,因为总共有n个元素,所以至多需要n-1次交换(交换完n-1个元素,第n个元素自动满足)即可使所有的元素处在正确位置,也即while循环至多执行O(n)次,每次的平摊代价是O(1)。所以上述交换操作的复杂度为O(n)。
C语言版代码如下:
void swap(int *a,int *b)
{
int temp=*a;
*a=*b;
*b=temp;
}
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize) {
int* result=(int*)malloc(sizeof(int)*numsSize);
for(int i=0;i<numsSize;i++)
{
while(nums[i]!=i+1&&nums[nums[i]-1]!=nums[i])
{
swap(&nums[i],&nums[nums[i]-1]);
}
}
*returnSize=0;
for(int i=0;i<numsSize;i++)
{
if(nums[i]!=i+1)
{
result[*returnSize]=i+1;
*returnSize=*returnSize+1;
}
}
return result;
}
解法二
在待字闺中公众号《数组统计分析》中,陈利人老师曾经给出另外一种解法—取余法,道理也比较好理解。数组的元素范围为1~n,第一次循环首先把每个元素对应的位置加上(n+1);第二次循环把每个位置除以(n+1),如果该位置为0,表示某个元素没有出现;如果该位置等于2,表示出现两次。
原理是什么呢?在第一次循环中,我们其实是将每个位置变成k*(n+1)+i,其中k表示该位置加(n+1)的次数,取值为0、1、2,i表示该位置本来的元素。在第二次循环中,因为i的范围是1~n,所以除以(n+1)就等于0,从而我们就获得了k的值。根据k的值,我们就很容易知道哪些元素没有出现,哪些元素出现了多次。
C语言版代码如下:
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize) {
int* result=(int*)malloc(sizeof(int)*numsSize);
*returnSize=0;
for(int i=0;i<numsSize;i++)
{
nums[nums[i]%(numsSize+1)-1]+=(numsSize+1);
}
for(int i=0;i<numsSize;i++)
{
if(nums[i]/(numsSize+1)==0)
{
result[*returnSize]=i+1;
*returnSize=*returnSize+1;
}
}
return result;
}
解法三
在Top Solution中,有网友分享了一种很奇妙的解法—取负法。含义是:将元素对应的位置取负。简单一句话可能不好理解,我们举个例子。假设在位置k放了元素i,则在取负的过程中i的取值有两种可能:为正,表示当前尚未遇到元素k将该位置取负;为负,表示当前已经有元素k出现,并将元素取负。但是我们不关心k,我们关心元素i。元素i既然出现,我们就看一下位置i:为正,表示这是元素i第一次出现,我们将位置i取负;为负,表示元素i已经出现过一次,我们不做任何操作。不管一个元素出现一次还是两次,只要出现它对应的位置就会被取负。当某个元素不出现的时候,该元素对应的位置始终访问不到,所以还是正值,通过这种方法我们就可以找到哪些元素没有出现。
通过上面的分析我们也很容易知道,在取负的过程中,如果发现要取负的位置已经为负,说明这个元素已经出现过,也即该元素出现了两次,我们可以将该元素保留下来。
C语言版代码如下:
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize) {
int* result=(int*)malloc(sizeof(int)*numsSize);
for(int i=0;i<numsSize;i++)
{
int index=abs(nums[i])-1;
if(nums[index]>0) nums[index]=-nums[index];
}
*returnSize=0;
for(int i=0;i<numsSize;i++)
{
if(nums[i]>0)
{
result[*returnSize]=i+1;
*returnSize=*returnSize+1;
}
}
return result;
}
针对《Find All Duplicates in an Array》,采用取负法实现的C语言代码如下:
int* findDuplicates(int* nums, int numsSize, int* returnSize) {
int* result=(int*)malloc(sizeof(int)*numsSize);
*returnSize=0;
for(int i=0;i<numsSize;i++)
{
int index=abs(nums[i])-1;
if(nums[index]>0)
{
nums[index]=-nums[index];
}
else
{
result[*returnSize]=index+1;
*returnSize=*returnSize+1;
}
}
return result;
}
leetcode之Find All Numbers Disappeared in an Array的更多相关文章
- LeetCode 448. Find All Numbers Disappeared in an Array (在数组中找到没有出现的数字)
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and ot ...
- leetcode 448. Find All Numbers Disappeared in an Array -easy (重要)
题目链接: https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/description/ 题目描述: Give ...
- LeetCode "448. Find All Numbers Disappeared in an Array"
My first reaction is to have an unlimited length of bit-array, to mark existence. But if no extra me ...
- 5. Leetcode 448. Find All Numbers Disappeared in an Array
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and ot ...
- LeetCode 448 Find All Numbers Disappeared in an Array 解题报告
题目要求 Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice a ...
- LeetCode: 448 Find All Numbers Disappeared in an Array(easy)
题目: Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice an ...
- LeetCode 448. Find All Numbers Disappeared in an Array找到所有数组中消失的元素
题目 给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次. 找到所有在 [1, n] 范围之间没有出现在数组中的数字. 您能 ...
- [LeetCode] 448. Find All Numbers Disappeared in an Array 找到数组中消失的数字
题目描述 给定n个数字的数组,里面的值都是1-n,但是有的出现了两遍,因此有的没有出现,求没有出现值这个数组中的值有哪些. 要求不能用额外的空间(除了返回列表之外),时间复杂度n 思路 因为不能用额外 ...
- LeetCode——Find All Numbers Disappeared in an Array
LeetCode--Find All Numbers Disappeared in an Array Question Given an array of integers where 1 ≤ a[i ...
随机推荐
- DBSCAN
DBSCAN,英文全写为Density-based spatial clustering of applications with noise ,是在 1996 年由Martin Ester, Han ...
- 在Visual Studio2017和2015中开发报表项目
1.在sqlserver2008的安装目录中是自带了一个报表开发工具的,但在sqlserver2016中没找到,我推测sqlserver2014也没有,哈,我不探寻这个: 2.在VS2015中想要开发 ...
- from sys import argv
from sys import argv 初学理解: sys 为内置模块,提供了许多函数和变量来处理 Python 运行时环境的不同部分.是固定的用法,不能自己随便写名字代替它,这行的作用就是要把用 ...
- vue.js初识(一)
一 什么是vue? Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不 ...
- Ubuntu+Firefox总是打不开网页
参考链接 火狐的设置里面找: 首选项 -> 高级 -> 网络 -> 连接 -> 设置, 结果发现之前默认是选择了使用系统代理设置, 果断拒绝!... 勾选第一项, " ...
- eclipse点击包(package)时报错,安装hibernate后点击包报错org/eclipse/jpt/common/utility/exception/ExceptionHandler
错误描述: 当我们点击包名时,出现如下错误提示.An error has occurred. See error log for more details.org/eclipse/jpt/common ...
- iOS 同一个workspace下创建多个项目编程
在iOS开发中,相关联的多个项目可能会放在同一个workspace下进行开发,那习惯了一个项目在一个工作空间下的同学该怎么快速开撸呢? 只需要三步而已! 第一步,先用Xcode在目标目录下创建一个wo ...
- mysql优化2:列类型选择原则
1.字段类型优先级 整型>date,time>enum,char>varchar>blog,text 列的特点分析: 整型:定长,没有国家/地区之分,没有字符集的差异 比如ti ...
- [LeetCode] Next Greater Element I 下一个较大的元素之一
You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subset of n ...
- Mac终端开启代理
使用shadowsocks开启代理,只支持浏览器开启代理,其他软件是不能够开启代理的,因为这个问题,自己一直无法用本地终端 git clone 一些库,网上查找方法,总结如下: 步骤一:开启shado ...