领扣(LeetCode)错误的集合 个人题解

集合 S 包含从1到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复。

给定一个数组 nums 代表了集合 S 发生错误后的结果。你的任务是首先寻找到重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

示例 1:

输入: nums = [1,2,2,4]
输出: [2,3]

注意:

  1. 给定数组的长度范围是 [2, 10000]。
  2. 给定的数组是无序的。

拿到这题,正常的思路,拿一个hashmap记录出现的次数,如果多次出现即为重复的数,记录下来。然后用另外一个循环记录缺失的数。执行速度不稳定,最高打败了50%的人

代码如下:

 1 class Solution {
 2     public int[] findErrorNums(int[] nums) {
 3         int[] ans = new int[2];
 4         Map<Integer, Integer> map = new HashMap<>();
 5         for (int i = 0; i < ans.length; i++) {
 6             if (!map.containsKey(ans[i])) {
 7                 map.put(nums[i], 1);
 8             } else {
 9                 ans[0] = nums[i];
10             }
11         }
12         for (int i = 0; i < nums.length; i++) {
13             if (!map.containsKey(ans[i])) {
14                 ans[1] = nums[i];
15                 break;
16             }
17         }
18         return ans;
19 
20     }
21 }

考虑到Map的查找效率不是太高,于是改进版使用了一个标记数组来代替Map的功能。道理是一样的。形如 :标记数组[nums的值]=nums的值出现的个数 

首先赋值标记数组全部为0,然后遍历nums给标记数组赋值,最后遍历标记数组,如果标记数组在index的值为2,则index这个数重复了两次,如果在index这个位置的值为0,则说明index这个数没有出现过。

这样做的效率变高了许多。

代码如下:

 1 class Solution {
 2     public int[] findErrorNums(int[] nums) {
 3         int[] ans = new int[2];
 4         int[] mark=new int[nums.length+1];
 5         Arrays.fill(mark, 0);
 6         for(int i=0;i<nums.length;i++)
 7         {
 8             mark[nums[i]]++;
 9         }
10         for(int i=1;i<mark.length;i++)
11         {
12             if(mark[i]==2)
13                 ans[0]=i;
14             if(mark[i]==0)
15                 ans[1]=i;
16         }
17         return ans;
18     }
19 }
原文地址:https://www.cnblogs.com/axiangcoding/p/10010140.html