-.查找缺失和重复的元素
给一个长度为 N
的数组 nums
,其中本来装着 [1..N]
这 N
个元素,无序。但是现在出现了一些错误,nums
中的一个元素出现了重复,也就同时导致了另一个元素的缺失。请你写一个算法,找到 nums
中的重复元素和缺失元素的值。
分析: 重复的数字在数组中出现 2 次,丢失的数字在数组中出现 0 次,其余的每个数字在数组中出现 1 次。因此可以使用哈希表记录每个元素在数组中出现的次数,然后遍历从 1 到 n 的每个数字,分别找到出现 2 次和出现 0 次的数字,即为重复的数字和丢失的数字。
1.使用哈希表
public class FindDumAndMis { public int[] find(int[] array) { HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); int[] errorNums = new int[2]; for (int num: array) { map.put(num, map.getOrDefault(num, 0) + 1); } for (int i = 0; i < array.length; i++) { Integer count = map.getOrDefault(i, 0); if (count == 2) { errorNums[0] = i; }else if (count == 0) { errorNums[1] = i; } } return errorNums; } }
2.排序
将 nums
中的元素变为 [0..N-1]
,这样每个元素就和一个数组索引完全对应了, 通过将每个索引对应的元素变成负数,以表示这个索引被对应过一次了:
这样会导致有两个元素对应到了同一个索引(重复),而且会有一个索引没有元素对应过去(缺失)。
class Solution { public int[] findErrorNums(int[] nums) { int n = nums.length; int dup = -1; for (int i = 0; i < n; i++) { // 元素是从 1 开始的 int index = Math.abs(nums[i]) - 1; // nums[index] 小于 0 则说明重复访问 if (nums[index] < 0) dup = Math.abs(nums[i]); else nums[index] *= -1; } int missing = -1; for (int i = 0; i < n; i++) // nums[i] 大于 0 则说明没有访问 if (nums[i] > 0) // 将索引转换成元素 missing = i + 1; return new int[]{dup, missing}; } }