「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战」。
题目描述🌍
给定一个包含 [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.length1 <= n <= 1040 <= nums[i] <= nnums中的所有数字都 独一无二
进阶:你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?
排序📈
解题思路
数组排序后,当遍历数组元素不满足 i==nums[i] 则表明丢失的值为 i;若给定数组中的元素都满足 i==nums[i],则丢失的元素在最后一位,返回 nums.length。
代码
Java
class Solution {
public int missingNumber(int[] nums) {
Arrays.sort(nums);
int length = nums.length;
for (int i = 0; i < length; i++) {
if (nums[i] != i)
return i;
}
return length;
}
}
C++
class Solution {
public:
int missingNumber(vector<int> &nums) {
sort(nums.begin(), nums.end());
int length = nums.size();
for (int i = 0; i < length; ++i) {
if (nums[i] != i)
return i;
}
return length;
}
};
时间复杂度:
空间复杂度:
哈希法🍤
解题思路
通过哈希集合可以有效降低时间复杂度。
遍历数组,将所有元素加入到哈希集合中,然后依次检查 0 到 n 哪个元素不在哈希集合中。
代码
Java
class Solution {
public int missingNumber(int[] nums) {
Set<Integer> hashSet = new HashSet<>();
for (int num : nums) {
hashSet.add(num);
}
int length = nums.length;
for (int i = 0; i <= length; i++) {
if (!hashSet.contains(i))
return i;
}
return -1;
}
}
C++
class Solution {
public:
int missingNumber(vector<int> &nums) {
unordered_set<int> hash;
for (int num: nums) {
hash.insert(num);
}
int length = nums.size();
for (int i = 0; i < length; ++i) {
if (hash.find(i) == hash.end())
return i;
}
return length;
}
};
时间复杂度:
空间复杂度:
差值法🚀
解题思路
既然是查找 中丢失的数字,那么索性将 所有数字进行累加,然后减去数组中的所有元素, 其差值就是所求的丢失数字。
🚄高斯公式求和:
代码
Java
class Solution {
public int missingNumber(int[] nums) {
int length = nums.length;
int sum = accumulation(length);
for (int i = 0; i < length; i++) {
sum -= nums[i];
}
return sum;
}
// sum = n*(n+1)/2
private int accumulation(int n) {
return n * (n + 1) / 2;
}
}
C++
class Solution {
public:
int missingNumber(vector<int> &nums) {
int sum = accumulation(nums.size());
int missingSum = accumulate(nums.begin(), nums.end(), 0);
return sum - missingSum;
}
int accumulation(int n) {
return n * (n + 1) / 2;
}
};
时间复杂度:
空间复杂度:
位运算「异或」🥇
解题思路
⭐异或运算规则:
x ^ 0 = xx ^ x = 0x ^ y ^ z = x ^ z ^ y
除了丢失的数字出现 0 次,其余数字皆出现了 1 次,那么我们可以再为它创造一个 0 到 n 的数组,这时丢失的数字出现 1 次,其余数字皆出现了 2 次。然后将这 2n+1 个元素进行异或运算,即可获得只出现 1 次的丢失数字了。
不过进阶要求空间复杂度为 ,那么我们用时间换空间,不创建数组了,直接逐一异或 0 到 n 的元素。
一图胜千言(举个栗子)
代码
Java
class Solution {
public int missingNumber(int[] nums) {
int x = 0;
int length = nums.length;
for (int i = 0; i < length; i++) {
x ^= nums[i];
x ^= i;
}
x ^= length;
return x;
}
}
C++
class Solution {
public:
int missingNumber(vector<int> &nums) {
int length = nums.size();
int ret = 0;
for (int i = 0; i < length; ++i) {
ret ^= nums[i];
ret ^= i;
}
ret ^= length;
return ret;
}
};
时间复杂度:
空间复杂度:
最后🌅
该篇文章为 「LeetCode」 系列的 No.20 篇,在这个系列文章中:
- 尽量给出多种解题思路
- 提供题解的多语言代码实现
- 记录该题涉及的知识点
👨💻争取做到 LeetCode 每日 1 题,所有的题解/代码均收录于 「LeetCode」 仓库,欢迎随时加入我们的刷题小分队!