题目:集合s包含从1到n的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合丢失了一个数字并且有一个数字重复。
给定一个数组nums代表了集合s发生错误后的结果。请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例1:
输入:nums = [1,2,2,4]
输出:[2,3]
示例2:
输入:nums = [1,1]
输出:[1,2]
提示:
2 <= nums.length <= 104% \f is defined as #1f(#2) using the macro
10^4104
1 <= nums[i] <= 104% \f is defined as #1f(#2) using the macro
10^4104
实现思路:
方法一:
首先想到的是暴力解法,即挨个遍历将出现重复的数字放入新申请的数组中。明显这种方法的时间消耗很大,并且往往头脑中出现的第一种解法并不是最优解。
方法二:
先排序,检查出连续出现的数字,再检查相邻的两个数字相差多少,找到缺失的数字。
C++实现:
class Solution {
public:
vector<int> findErrorNums(vector<int>& nums) {
vector<int> res;
for (int i = 0; i < nums.size(); i++) {
while (nums[i] != nums[nums[i] - 1]) {
swap(nums[i], nums[nums[i] - 1]);
}
}
for (int i = 0; i < nums.size(); i++) {
if (nums[i] != i + 1) {
return { nums[i], i + 1 };
}
}
return res;
}
};
方法三:
(这个方法是浏览大佬们解题发现的,发现真的简单)使用Map,如果我们知道nums中每个数字出现的次数,就可以轻松的解决问题。使用map存储nums中每个数字的出现次数。存储形式为(numi,counti),表示数字numi一共出现了counti次。当一个元素重复出现时,它的计数就加1。再检查1到n的每个数字在map中出现次数。如果一个数字在map中没有出现,它就是缺失数字。如果一个数字的出现了两次,它就是重复数字。
C++实现:
class Solution {
public:
vector<int> findErrorNums(vector<int>& nums) {
int n = nums.size();
int err = 0;
vector<int> mp(n + 1, 0);
int error = 0;
for(int i = 0; i < n; ++i){
err ^= (nums[i] ^ (i + 1));
mp[nums[i]]++;
if(mp[nums[i]] == 2){
error = nums[i];
}
}
return {error, error ^ err};
}
};