错误的集合
集合 S 包含从1到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复。
给定一个数组 nums 代表了集合 S 发生错误后的结果。你的任务是首先寻找到重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例 1:
输入: nums = [1,2,2,4]
输出: [2,3]
注意:
给定数组的长度范围是 [2, 10000]。
给定的数组是无序的。
解法一(数学思想)
- 等差数列求和
- 错误的集合求和
- 得到重复数字与缺失数字的关系
- 找出重复数字,并返回结果
var findErrorNums = function(nums) {
var len = nums.length
nums.sort((a, b)=>{
return a-b
})// 排序后,重复的数字一定相邻
var sum1 = (1+len)*len/2
var sum2 = 0
var item1 = 0
var item2 = 0
for(let i = 0; i < nums.length; i++){
sum2+= nums[i]
if(nums[i] === nums[i+1]){
item1 = nums[i]
}
}
// 缺失数字 - 重复数字 = sum1 - sum2
item2 = item1+sum1-sum2
return [item1, item2]
};
解法二(Map)
- 利用Map降低时间复杂度
var findErrorNums = function(nums) {
var len = nums.length;
var obj = {};
var sum1 = (1 + len) * len / 2;
var sum2 = 0;
var item1 = 0; // 重复数字
var item2 = 0; // 缺失数字
nums.forEach(item => {
sum2 += item
if (obj[item]) {
item1 = item
}else{
obj[item] = 1
}
});
// 缺失数字 - 重复数字 = sum1 - sum2
item2 = item1 + sum1 - sum2;
return [item1, item2]
};
解法三(暴力解法)
- 时间复杂度O(n^2)
- 时间复杂度O(1)
- 双重循环,记录
1-n
的数字出现次数
var findErrorNums = function(nums) {
var len = nums.length;
let drp = -1;
let missing = -1;
for (let i = 1; i <= len; i++) {
let count = 0;
for (let j = 0; j < len; j++) {
if (nums[j] == i)
count++;
}
if (count == 2)
drp = i;
else if (count == 0)
missing = i;
}
return [drp, missing]
};
解法四(使用异或运算)
算法
思考一个简单的问题,一个长度为 n−1
的数组,有一个数字缺失,如何找出这个缺失的数字。首先使用 1 到 n 的所有数字做异或运算,然后再使用数组中的所有数字与这个数字异或,最后得到的值就是缺失数字。因为数字与其本身做异或运算结果为 0,因此所有数字做完异或后,剩余的就是缺失的数字。