错误的集合_leetcode

Posted 勇敢牛牛不怕困难@帅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了错误的集合_leetcode相关的知识,希望对你有一定的参考价值。

力扣第645.题------错误的集合

在这里插入图片描述
题目:
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
在这里插入图片描述
分析:
根据题目的意思1到n的数字,原本应该是连续且单一的,然而在复制的过程种出现了复制出错的情况,题目的意思就是要我们找出重复出现的整数和原本的数字。将数组排序之后,比较每对相邻的元素,即可找到错误的集合。寻找重复的数字较为简单,如果相邻的两个元素相等,则该元素为重复的数字。寻找丢失的数字相对复杂,可能有以下两种情况:

  • 如果丢失的数字大于 1且小于 n,则一定存在相邻的两个元素的差等于 2,这两个元素之间的值即为丢失的数字;
  • 如果丢失的数字是 1或 n,则需要另外判断。

为了寻找丢失的数字,需要在遍历已排序数组的同时记录上一个元素,然后计算当前元素与上一个元素的差。考虑到丢失的数字可能是 11,因此需要将上一个元素初始化

所以最后的思路就是小于n值我们根据两数之差来判断丢失的数字,而n最后一个数字需要另做判断。
代码:

 public int[] findErrorNums(int[] nums) {
        int[] errorNums = new int[2];//声明一个数组,作为返回对象
        int n = nums.length;//nums的长度
        Arrays.sort(nums);//对nums进行排序
        int prev = 0;//记录重复元素
        for (int i = 0; i < n; i++) {
            int curr = nums[i];
            if (curr == prev) {
                errorNums[0] = prev;
            } else if (curr - prev > 1) {
                errorNums[1] = prev + 1;
            }
            prev = curr;
        }
        if (nums[n - 1] != n) {
            errorNums[1] = n;
        }
        return errorNums;
    }
    public static void main(String[] args) {

		int n[] = {1,2,4,2,5,6};
		int m[] = findErrorNums(n);
		System.out.println(m[0]+"   "+m[1]);
	}

结果:
在这里插入图片描述

第二种解题方式hash表:
重复的数字在数组中出现 2 次,丢失的数字在数组中出现 0 次,其余的每个数字在数组中出现 1 次。因此可以使用哈希表记录每个元素在数组中出现的次数,然后遍历从 1 到 n 的每个数字,分别找到出现 2 次和出现 0 次的数字,即为重复的数字和丢失的数字。

代码:

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;
    }
}

第三种解题方法
重复的数字在数组中出现 22 次,丢失的数字在数组中出现 00 次,其余的每个数字在数组中出现 11 次。由此可见,重复的数字和丢失的数字的出现次数的奇偶性相同,且和其余的每个数字的出现次数的奇偶性不同。如果在数组的 nn 个数字后面再添加从 11 到 nn 的每个数字,得到 2n2n 个数字,则在 2n2n 个数字中,重复的数字出现 33 次,丢失的数字出现 11 次,其余的每个数字出现 22 次。根据出现次数的奇偶性,可以使用异或运算求解。

class Solution {
    public int[] findErrorNums(int[] nums) {
        int n = nums.length;
        int xor = 0;
        for (int num : nums) {
            xor ^= num;
        }
        for (int i = 1; i <= n; i++) {
            xor ^= i;
        }
        int lowbit = xor & (-xor);
        int num1 = 0, num2 = 0;
        for (int num : nums) {
            if ((num & lowbit) == 0) {
                num1 ^= num;
            } else {
                num2 ^= num;
            }
        }
        for (int i = 1; i <= n; i++) {
            if ((i & lowbit) == 0) {
                num1 ^= i;
            } else {
                num2 ^= i;
            }
        }
        for (int num : nums) {
            if (num == num1) {
                return new int[]{num1, num2};
            }
        }
        return new int[]{num2, num1};
    }
}

以上是关于错误的集合_leetcode的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode_645_数组_错误集合

leetcode_1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold_[二维前缀和](代码片段

LeetCode题目记录-645. 错误的集合(C++代码实现)

比较 C# 中的字符串片段并从集合中删除项目

LeetCode 645 错误的集合[Map 桶排序 双指针] HERODING的LeetCode之路

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