题目链接:268. 丢失的数字
题目:
给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
示例 1:
输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
示例 2:
输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。
示例 3:
输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。
示例 4:
输入:nums = [0]
输出:1
解释:n = 1,因为有 1 个数字,所以所有的数字都在范围 [0,1] 内。1 是丢失的数字,因为它没有出现在 nums 中。
提示:
- n == nums.length
- 1 <= n <= 104
- 0 <= nums[i] <= n
- nums 中的所有数字都 独一无二
进阶:你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?
代码(c++):
方案一:哈希表
往哈希表里插入nums中所有元素,然后再循环[0, n]区间进行查找 i ,i 如果在哈希表中不存在,那么 i 就是缺失的那个数字,
//哈希表
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n = nums.size();
unordered_set<int> set; //存放nums中的元素
for (int x : nums) {
set.insert(x);
}
int i;
for (i = 0; i <= n; ++i) { //数字范围[0, n]
if (!set.count(i)) //如果没有找到,则是缺失的那个数字
break;
}
return i;
}
};
方案二:桶排序
额外开辟一片 n + 1 大小的空间bucket,并全部初始化值为0,nums数组中的元素作为下标,出现的元素值为1。而后遍历bucket数组,发现值为0的元素,则返回值对应的索引下标 i 。
//桶排序
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n = nums.size();
vector<int> bucket(n + 1, 0);
int i;
for (i = 0; i < n; ++i) {
bucket[nums[i]]++;
}
i = 0;
while (i < bucket.size()) {
if (!bucket[i]) break;
++i;
}
return i;
}
};
方案三:sort排序
用sort方法对nums数组进行排序,然后对排好序的数组进行遍历,如果遇到元素和其所对应的下标不匹配,则返回下标。
//sort排序
class Solution {
public:
int missingNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int i;
for (i = 0; i < nums.size(); ++i) {
if (nums[i] != i) break;
}
return i;
}
};
方案四:位运算
相同元素做位运算为0,不为零的元素和零做位运算还是本身。先让nums数组中的元素相互做位运算,然后再和[0, n]中的数组做位运算,因为nums中除了缺失的数字,其他和[0, n]中的数字都成双成对,所以一轮位运算下来,结果只剩下缺失的那个数字,返回结果即可。
//位运算:相同元素做位运算为0,不为零的元素和零做位运算还是本身
class Solution {
public:
int missingNumber(vector<int>& nums) {
int ans = 0;
for (int i = 0; i < nums.size(); ++i) {
ans ^= nums[i];
}
for (int i = 0; i <= nums.size(); ++i) {
ans ^= i;
}
return ans;
}
};