题目:

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this array.

Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.

Example:

Input:
[4,3,2,7,8,2,3,1] Output:
[5,6]

代码:

在网上搜了搜,找到了几种解法,写好程序后整理整理。

解法一(取余法):

数组的元素范围为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的值,我们就很容易知道哪些元素没有出现,哪些元素出现了多次。

 class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> result;
int length = nums.size()+;
for (int i = ; i < length-; i++)
nums[nums[i]%length-] += length;
for (int i = ; i < length-; i++){
if ((nums[i]/length) == )
result.push_back(i+);
}
return result;
}
};

解法二(元素归位法):

元素归位法很容易理解,就是将n个元素交换到它应该在的位置。例如,元素5就放到位置4(下标从0开始)。这里需要注意一点,将某个元素交换到正确位置可能会导致当前位置的元素还不在正确位置,需要继续交换直到不能交换为止,伪代码如下:

 for i=: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)。

 class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> result;
int length = nums.size()+;
for (int i = ; i < length-; i++){
while((nums[i] != i+ )&& (nums[nums[i]-] != nums[i]))
swap(nums[i],nums[nums[i]-]);
} for (int i = ; i < length-; i++){
if (nums[i] != i+)
result.push_back(i+);
}
return result;
}
};

运行最快。

解法三(取负法):

含义是:将元素对应的位置取负。简单一句话可能不好理解,我们举个例子。假设在位置k放了元素i,则在取负的过程中i的取值有两种可能:为正,表示当前尚未遇到元素k将该位置取负;为负,表示当前已经有元素k出现,并将元素取负。但是我们不关心k,我们关心元素i。元素i既然出现,我们就看一下位置i:为正,表示这是元素i第一次出现,我们将位置i取负;为负,表示元素i已经出现过一次,我们不做任何操作。不管一个元素出现一次还是两次,只要出现它对应的位置就会被取负。当某个元素不出现的时候,该元素对应的位置始终访问不到,所以还是正值,通过这种方法我们就可以找到哪些元素没有出现。 
通过上面的分析我们也很容易知道,在取负的过程中,如果发现要取负的位置已经为负,说明这个元素已经出现过,也即该元素出现了两次,我们可以将该元素保留下来。

 class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> result;
int length = nums.size();
for (int i = ; i < length; i++){
int index = abs(nums[i])-;
if(nums[index]>)
nums[index] = -nums[index];
} for (int i = ; i < length; i++){
if (nums[i] > )
result.push_back(i+);
}
return result;
}
};

这三种方法都是通过某种方式将index与元素对应起来操作。

LeetCode: 448 Find All Numbers Disappeared in an Array(easy)的更多相关文章

  1. leetcode 448. Find All Numbers Disappeared in an Array -easy (重要)

    题目链接: https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/description/ 题目描述: Give ...

  2. 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 ...

  3. 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 ...

  4. 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 ...

  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 a ...

  6. LeetCode 448. Find All Numbers Disappeared in an Array找到所有数组中消失的元素

    题目 给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次. 找到所有在 [1, n] 范围之间没有出现在数组中的数字. 您能 ...

  7. [LeetCode] 448. Find All Numbers Disappeared in an Array 找到数组中消失的数字

    题目描述 给定n个数字的数组,里面的值都是1-n,但是有的出现了两遍,因此有的没有出现,求没有出现值这个数组中的值有哪些. 要求不能用额外的空间(除了返回列表之外),时间复杂度n 思路 因为不能用额外 ...

  8. 【leetcode】448. Find All Numbers Disappeared in an Array

    problem 448. Find All Numbers Disappeared in an Array solution: class Solution { public: vector<i ...

  9. leetcode 217. Contains Duplicate 287. Find the Duplicate Number 442. Find All Duplicates in an Array 448. Find All Numbers Disappeared in an Array

    后面3个题都是限制在1-n的,所有可以不先排序,可以利用巧方法做.最后两个题几乎一模一样. 217. Contains Duplicate class Solution { public: bool ...

随机推荐

  1. Ubuntu引导出问题grub rescu模式下:“error : unknown filesystem”或者 找不到normal.mod 的解决办法

    感谢http://www.linuxidc.com/Linux/2012-06/61983.htm,因为参考了其中的内容. 下面是修改和完善. 问题原因: (win7,ubuntu双系统下) 强制关机 ...

  2. Dash 使用

    花了 160 买了这个软件,至少看一遍它的 user guide,钱不能白花. https://kapeli.com/guide/guide.html 设置全局快捷键 Preference -> ...

  3. openwrt spi flash 分区适配过程

    openwrt spi flash 分区适配过程 这里基于 openwrt mt7620a 平台来跟踪,主要是想理清 dts 里的分区描述是如何一步步转化成内核分区行为. 先来看看 dts 中关于分区 ...

  4. Android-基本控件和详解四种布局方式

    转自:https://www.cnblogs.com/ludashi/p/4883915.html 一.常用基本控件 1.TextView 看到Android中的TextView, 我不禁的想到了iO ...

  5. EasyRTMP实现的rtmp推流的基本协议流程

    EasyRTMP介绍 EasyRTMP是结合了多种音视频缓存及网络技术的一个rtmp直播推流端,包括:圆形缓冲区(circular buffer).智能丢帧.自动重连.rtmp协议等等多种技术,能够非 ...

  6. Ubuntu安装搜狗输入法笔记

    1.移除ibus sudo apt-get purge ibussudo apt-get autoremove 2.安装fcitx sudo apt-get install fcitx 3.安装搜狗输 ...

  7. Machine Learning in Action(3) 朴素贝叶斯算法

    贝叶斯决策一直很有争议,今年是贝叶斯250周年,历经沉浮,今天它的应用又开始逐渐活跃,有兴趣的可以看看斯坦福Brad Efron大师对其的反思,两篇文章:“Bayes'Theorem in the 2 ...

  8. linux 启动引导器 grub,单用户模式:

    Linux启动引导器 安装linux操作系统的时候就已经将启动引导器安装到硬盘上去了,才能通过硬盘的读取方式启动操作系统. 引导器分为2种: Lilo:功能比较简单,使用比较麻烦,后续发行版中使用gr ...

  9. spring cloud - 注册中心

    服务注册与发现 这里我们会用到Spring Cloud Netflix,该项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用 ...

  10. Codeforces Round #394 (Div. 2) C. Dasha and Password —— 枚举

    题目链接:http://codeforces.com/problemset/problem/761/C C. Dasha and Password time limit per test 2 seco ...