0
点赞
收藏
分享

微信扫一扫

448. *Find All Numbers Disappeared in an Array

448. *Find All Numbers Disappeared in an Array

​​https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/description/​​

题目描述

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 448. *Find All Numbers Disappeared in an Array_数组 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​​​ 之间的, 可能就可以考虑使用将元素值作为索引的方法… 由于每个元素值的大小都是 ​​1 <= a[i] <= N​​​, 那么访问 ​​a[a[i] - 1]​​ 是没有问题的. 考虑上面这个数组:

# 假设数组的索引从 1 开始
index : 1 2 3 4 5 6 7 8
value : 4 3 2 7 8 2 3 1

现在从索引 ​​1​​​ 开始, 如果依次将 ​​a[abs(a[i])]​​​ 的值改为负数, 但如果 ​​a[abs(a[i])]​​ 已经是负数了, 那么就不用修改了.

# 假设数组的索引从 1 开始
index : 1 2 3 4 5 6 7 8
value : -4 -3 -2 -7 8 2 -3 -1

可以看到只有 ​​{5, 6}​​​ 处的元素依然是正数, 那么消失的数字就是 ​​{5, 6}​​​. 由于下面的代码中索引从 ​​0​​​ 开始, 所以最后要加 ​​1​​.

核心思路就是: 对于 ​​nums​​​ 中的每个元素, 将 ​​nums[i] - 1​​ 对应的那个元素设置为负值, 表示那个元素已经被访问过.

C++ 实现 1

通过将 ​​nums[std::abs(nums[i]) - 1] > 0​​​ 的数值设置为负, 从而得到结果. 时间复杂度为 448. *Find All Numbers Disappeared in an Array_数组_02.

class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
for (int i = 0; i < nums.size(); ++i)
if (nums[std::abs(nums[i]) - 1] > 0)
nums[std::abs(nums[i]) - 1] *= -1;
vector<int> res;
for (int i = 0; i < nums.size(); ++i)
if (nums[i] > 0)
res.push_back(i + 1);
return res;
}
};

扩展阅读

leetcode 上的解答:

​​Java accepted simple solution​​

The basic idea is that we iterate through the input array and mark elements as negative using ​​nums[nums[i] -1] = -nums[nums[i]-1]​​. In this way all the numbers that we have seen will be marked as negative. In the second iteration, if a value is not marked as negative, it implies we have never seen that index before, so just add it to the return list.

public List<Integer> findDisappearedNumbers(int[] nums) {
List<Integer> ret = new ArrayList<Integer>();

for(int i = 0; i < nums.length; i++) {
int val = Math.abs(nums[i]) - 1;
if(nums[val] > 0) {
nums[val] = -nums[val];
}
}

for(int i = 0; i < nums.length; i++) {
if(nums[i] > 0) {
ret.add(i+1);
}
}
return ret;
}

最为关键的是下面的解释:

大致意思可以理解为, 对于 ​​nums​​​ 中的每个元素, 将 ​​nums[i] - 1​​​ 对应的那个元素设置为负值, 表示那个元素已经被访问过, 之后判断 ​​nums​​​ 中哪些值为正的, 如果为正, 说明对应的索引 ​​i + 1​​​ 不存在在 ​​nums​​ 中.

​​https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/discuss/92956/Java-accepted-simple-solution/97460​​

A more detailed explanation for those who might still be confused:

This solution is using the relation between array index ​​([0, n-1])​​​ and the given value range ​​[1,n]​​.

Each time when a new value ​​X​​​ is read, it changes the corresponding ​​X​​​th number (value at index ​​X-1​​​) into negative, indicating value ​​X​​​ is read for the first time. For example. using the given test case ​​[4,3,2,7,8,2,3,1]​​​, when it comes to ​​i = 2​​​ in the first loop, this solution marks the ​​2nd​​​ number (​​index = 1​​​), indicating we’ve found number ​​2​​ for the first time.

When we encounter a redundant number ​​Y​​​, because we’ve marked the ​​Yth​​​ position (​​index Y -1​​​) when we saw ​​Y​​​ for the first time, the if clause won’t let us flip it again. This leaves the already marked ​​Y​​​th number (number at index ​​Y-1​​​) negative. For example, in the given test case, when ​​i = 5​​​, ​​val = |2| - 1 = 1​​​, ​​nums[1] = -3 < 0​​​. No flip operation is needed because we’ve found value ​​2​​ before.

Looping through the ​​1st​​​ loop takes 448. *Find All Numbers Disappeared in an Array_数组 time, flipping signs won’t take extra space.

The second loop checks the signs of the values at indices. If the sign at index ​​P​​​ is negative, it means value ​​P + 1​​​ is in the array. e.g. ​​nums[0] = -4​​​, so value ​​0+1 = 1​​​ is in the array. If the value at index ​​Q​​​ is positive, then value ​​Q + 1​​​ is not in the array. e.g. ​​nums[4] = 8 > 0​​​, value ​​4 + 1 = 5​​​, we add ​​5​​​ into the ​​ret​​ list.


举报

相关推荐

0 条评论