leetcode448 找到所有数组中消失的数字
对于这道题目,我们进行分析,题目的特点在于首先数组内数字的大小是小于等于数组大小的,意味着我们可以通过数组的大小来判断数组内数字的大小
思路1
- 我们先构建一个大小为nums.size()的数组,用来作为我们的统计表
- 然后遍历原数组,对于原数组中数字出现次数进行统计
vector<int> ret(nums.size(), 0);
for(int i = 0; i < nums.size(); i++)
{
ret[nums[i] - 1]++;
}
- 在得到我们已统计好的数组中,我们只需要查找数组中哪个数字为0就可以找到消失的数字了
该方法需要借助额外的数组
空间复杂度 O(n)
时间复杂度 O(n)
思路2
我们进一步考虑原地哈希,由于数组内的数字范围是确定的,那么我们能否通过交换的思想让数组中出现数字的正确位置加上n, n为数组大小
举例说明
[4,3,2,7,8,2,3,1]
按照我们的思想,对于数组中出现数字的正确位置
对于4而言他本来正确位置是nums[3],因此我们对nums[3]的数字加上n
更新后的数组为
[4,3,2,15,8,2,3,1]
对3处理后
更新后的数组
[4,3,10,15,8,2,3,1]
在对2进行处理的时候,我们发现原来2的位置已经被10替换,如果我们依然去寻找nums[10]的位置的话们就会发生数组越界
这里就体现了我们为什么加上的是n而不是任意一个数,我们想要让数组内的数字全都能落到[0–n-1]的区间,则需要进行(%)取余处理,这样数组内的所有数都可以映射到[0 — n-1],需要注意的是我们在进行取余的操作是
int x = (nums[i]-1) % size;
注意是nums[i - 1]% size
所以对数组[4,3,10,15,8,2,3,1]处理的结果为
[4,11,10,15,8,2,3,1]
通过这样处理,最终就可以在筛选出消失的数字了,因为消失数字的位置是没经过+n操作的,我们只需要遍历数组寻找小于等于size的位置就可以
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
//利用原有原数组使用哈希技巧
//code2 实现原地修改
//就在该数组的基础上 对于该数组进行处理,对于数组内每个数组,都在[1, N]的范围内,
//为了方便理解 我们去数组[1,2,2]
//我们对数组内的值让其加上n 对于数子1 它本该出现在下标为0的位置 所以我们让下标为0 的数据+n代表该位置数据已经出现过 对于缺少的3而言 由于数组中没有出现3 所以经过一轮转换之后 该位置数字会小于n
int size = nums.size();
for(int i = 0; i < size; ++i)
{
//存在数据有可能已经被处理过情况
//需要先对数据进行取余处理
int x = (nums[i]-1) % size;
nums[x] += size;
}
vector<int> ret;
for(int i = 0; i < size; ++i)
{
if(nums[i] <= size)
{
ret.push_back(i+1);
}
}
return ret;
}
};
该方法无需借助额外的数组
空间复杂度 O(1)
时间复杂度 O(n)
leetcode448 找到所有数组中消失的数字