645. 错误的集合
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例 1:
输入:nums = [1,2,2,4]
输出:[2,3]
示例 2:
输入:nums = [1,1]
输出:[1,2]
Solution
Using HashMap
class Solution {
public int[] findErrorNums(int[] nums) {
int[] errorNums = new int[2];
int n = nums.length;;
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
for (int i = 1; i <= n; ++i) {
int count = map.getOrDefault(i, 0);
if (count == 2) {
errorNums[0] = i;
} else if (count == 0) {
errorNums[1] = i;
}
}
return errorNums;
}
}
由于这里数的范围确定为 [1, n],我们可以使用数组来充当「哈希表」,以减少「哈希表」的哈希函数执行和冲突扩容的时间开销。
class Solution {
public int[] findErrorNums(int[] nums) {
int n = nums.length;
int[] cnts= new int[n + 1];
for (int x : nums) cnts[x]++;
int[] ans = new int[2];
for (int i = 1; i <= n; ++i) {
if (cnts[i] == 0) ans[1] = i;
if (cnts[i] == 2) ans[0] = i;
}
return ans;
}
}
因为值的范围在 [1, n],我们可以运用「桶排序」的思路,根据 nums[i] = i + 1 的对应关系使用 O(n)的复杂度将每个数放在其应该落在的位置里。然后线性扫描一遍排好序的数组,找到不符合 nums[i] = i + 1应关系的位置,从而确定重复元素和缺失元素是哪个值。In this case, the space complexity is o(1)
class Solution {
public int[] findErrorNums(int[] nums) {
int n = nums.length;
for (int i = 0; i < n; i++) {
while (nums[i] != i + 1 && nums[nums[i] - 1] != nums[i]) {
swap(nums, i, nums[i] - 1);
}
}
int a = -1, b = -1;
for (int i = 0; i < n; i++) {
if (nums[i] != i + 1) {
a = nums[i];
b = i == 0 ? 1 : nums[i - 1] + 1;
}
}
return new int[]{a, b};
}
void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}