leetcode 448. Find All Numbers Disappeared in an Array
Question
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]
问题
给定一个数组a,大小为n,数组元素的取值范围为[1,n]。每个数组元素会出现一次或者两次。现在要求在O(n)时间复杂度,并且不用任何额外空间,找出[1,n]这n个数字有哪些没有出现在数组中。
分析
问题的关键在于要达到时间复杂度O(n)和空间复杂度O(1)。时间复杂度O(n)要求我们只能遍历若干次数组;考虑到不能使用任何额外空间,我们必须在数组中完成所有操作。
使用正负号标记法。
1、第一次遍历数组,把当前元素nums[i]作为索引,将其所对应元素的绝对值取负,即nums[abs(nums[i])] = -abs(nums[abs(nums[i])]);
2、第一次遍历数组,把正数元素对应的下标+1加入结果集。
实际上,题目中给出的出现一次或者两次的条件是多余的。这种方法可以处理每个数字出现任意次的情况。
代码
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> disappearedNumbers;
for (int i = 0; i < nums.size(); i++)
{
nums[abs(nums[i]) - 1] = -abs(nums[abs(nums[i]) - 1]);
}
for (int i = 0; i < nums.size(); i++)
{
if (nums[i] > 0)
{
disappearedNumbers.push_back(i + 1);
}
}
return disappearedNumbers;
}
总结
1、O(n)时间复杂度只能遍历常数次输入;
2、O(1)空间复杂度要求只能修改输入,或者只创建常数个临时变量;
3、奇数vs偶数、出现vs没出现,这些情况可以考虑使用正负号标记法。