From 44fba1bcffc23d0ba0829a2521c9055defb063c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E6=A0=91=E6=A3=AE?= <14021051@buaa.edu.cn> Date: Sat, 8 Sep 2018 19:35:14 +0800 Subject: [PATCH] Create 448. Find All Numbers Disappeared in an Array.md --- ...ind All Numbers Disappeared in an Array.md | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 448. Find All Numbers Disappeared in an Array.md diff --git a/448. Find All Numbers Disappeared in an Array.md b/448. Find All Numbers Disappeared in an Array.md new file mode 100644 index 0000000..14e32cb --- /dev/null +++ b/448. Find All Numbers Disappeared in an Array.md @@ -0,0 +1,68 @@ +# [448. Find All Numbers Disappeared in an Array](https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/description/) +# 思路 +题目要求线性的时间复杂度且不适用额外的空间,所以最基本的先排序再判断就不行了。 +## 思路一 +依然是考虑将数组排序。由于数组元素的特殊性,其实每一个数在排序后应该在的位置是能立即确定的,例如2应该在nums[1], 5应该在nums[4]。 +所以我们从前往后遍历数组,不断循环将元素交换到应该在的位置,直到无法交换。 +无法交换的情况有二: +* nums[i] == i+1, 即已经在应该在的位置; +* nums[nums[i]-1] == nums[i], 即元素值等于期望交换的位置的元素值 + +仔细观察其实可以发现情况2包含了情况1, 所以代码中只写情况2就行了。 +如果满足交换条件,则每次都会使一个元素处在正确位置,因为总共有n个元素,所以至多需要n-1次交换, 所以时间复杂度O(n)。 +## 思路二 +我们只需要知道没有出现哪些元素,即第一次遍历的时候对已经出现的元素作个二值标记,第二次遍历时候寻找没有标记的位置即可。 +怎么进行标记呢?容易想到的就是开辟一个大小为n的标记数组(或者用map),但是有没有不用额外空间的办法呢? +由于nums就是一个大小为n的数组,所以我们考虑在不覆盖掉原有的元素(即第二次遍历时能够得到该位置原元素值)的基础上用nums作为标记数组。 +为了第二次遍历时能够得到该位置原元素值,有多种思路: +* 由于元素都是1~n的,所以如果对某元素加上n+1, 第二次遍历时对n+1取模即可得到原元素; +* 由于元素都是大于0的,所以使某元素为对应的负数也能达到目的。 + +因为加上n+1可能存在溢出的问题,所以我们采取第二种思路,即从前往后遍历, +将位置为nums[i]-1的元素变为对应的负数(即nums[abs(nums[i])-1] = -abs(nums[abs(nums[i])-1]))。 +第二次遍历时,若位置i上的数为正数,则缺失了数i+1。 +两次遍历,所以时间复杂度O(n) +# C++ +## 思路一 +``` +class Solution { +public: + vector findDisappearedNumbers(vector& nums) { + int tmp, i = 0; + while( i < nums.size()){ + if(nums[nums[i]-1] == nums[i]){ // 无法交换 + i++; + continue; + } + // 交换 + tmp = nums[nums[i]-1]; + nums[nums[i]-1] = nums[i]; + nums[i] = tmp; + } + + vectorresult; + for(int i = 0; i < nums.size(); i++) + if(nums[i] != (i + 1)) + result.push_back(i+1); + + return result; + } +}; +``` +## 思路二 +``` +class Solution { +public: + vector findDisappearedNumbers(vector& nums) { + for(int i = 0; i < nums.size(); i++) + nums[abs(nums[i]) - 1] = -1 * abs(nums[abs(nums[i]) - 1]); + + vectorresult; + for(int i = 0; i < nums.size(); i++) + if(nums[i] > 0) + result.push_back(i+1); + + return result; + } +}; +```