Easy
题目描述
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合丢失了一个数字并且有一个数字重复。
给定一个数组 nums 代表了集合 s 发生错误后的结果。
请你找出重复出现的整数,再找出丢失的整数,将它们以数组的形式返回。
示例 1:
输入:nums = [1,2,2,4]
输出:[2,3]
示例 2:
输入:nums = [1,1]
输出:[1,2]
提示:
2 <= nums.length <= 10^41 <= nums[i] <= 10^4
解题思路
这道题需要找出一个重复的数字和一个丢失的数字。有几种解法:
方法一:哈希表统计(推荐)
- 遍历数组,用哈希表统计每个数字的出现次数
- 再遍历 1 到 n,找出出现次数为 2 的数字(重复)和出现次数为 0 的数字(丢失)
- 时间复杂度 O(n),空间复杂度 O(n)
方法二:数学方法
- 设重复数字为 x,丢失数字为 y
- 利用求和公式:sum(nums) - sum(1…n) = x - y
- 利用平方和公式:sum(nums²) - sum(1²…n²) = x² - y²
- 联立方程求解 x 和 y
方法三:原地标记
- 利用数组下标,将访问过的位置标记为负数
- 如果发现某位置已经是负数,说明对应数字重复
- 最后遍历找出仍为正数的位置,对应丢失的数字
这里实现哈希表方法,代码简洁易懂且效率较高。
代码实现
class Solution {
public:
vector<int> findErrorNums(vector<int>& nums) {
int n = nums.size();
unordered_map<int, int> count;
// 统计每个数字出现次数
for (int num : nums) {
count[num]++;
}
int duplicate = -1, missing = -1;
// 找出重复和丢失的数字
for (int i = 1; i <= n; i++) {
if (count[i] == 2) {
duplicate = i;
} else if (count[i] == 0) {
missing = i;
}
}
return {duplicate, missing};
}
};
class Solution:
def findErrorNums(self, nums: List[int]) -> List[int]:
n = len(nums)
count = {}
# 统计每个数字出现次数
for num in nums:
count[num] = count.get(num, 0) + 1
duplicate = missing = -1
# 找出重复和丢失的数字
for i in range(1, n + 1):
if count.get(i, 0) == 2:
duplicate = i
elif count.get(i, 0) == 0:
missing = i
return [duplicate, missing]
public class Solution {
public int[] FindErrorNums(int[] nums) {
int n = nums.Length;
Dictionary<int, int> count = new Dictionary<int, int>();
// 统计每个数字出现次数
foreach (int num in nums) {
if (count.ContainsKey(num)) {
count[num]++;
} else {
count[num] = 1;
}
}
int duplicate = -1, missing = -1;
// 找出重复和丢失的数字
for (int i = 1; i <= n; i++) {
int currentCount = count.ContainsKey(i) ? count[i] : 0;
if (currentCount == 2) {
duplicate = i;
} else if (currentCount == 0) {
missing = i;
}
}
return new int[] {duplicate, missing};
}
}
var findErrorNums = function(nums) {
const n = nums.length;
const seen = new Set();
let duplicate = 0;
let sum = 0;
for (let num of nums) {
if (seen.has(num)) {
duplicate = num;
}
seen.add(num);
sum += num;
}
const expectedSum = n * (n + 1) / 2;
const missing = expectedSum - sum + duplicate;
return [duplicate, missing];
};
复杂度分析
| 复杂度类型 | 哈希表方法 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(n) |
其中 n 为数组长度。需要遍历数组一次统计频次,再遍历 1 到 n 找出结果,总时间复杂度为 O(n)。使用哈希表存储计数信息,空间复杂度为 O(n)。
相关题目
- . Find the Duplicate Number (Medium)