645 错误的集合

题目

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

给定一个数组 nums 代表了集合 S 发生错误后的结果。

请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

示例 1:

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

示例 2:

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

位运算

位运算的特点:

  • 满足 交换律结合律
  • 相同为 0,相异为 1
  • a ⊕ a = 0 a \oplus a = 0 aa=0
  • a ⊕ 0 = a a \oplus 0 = a a0=a

使用位运算,可以达到 O ( n ) O(n) O(n) 的时间复杂度和 O ( 1 ) O(1) O(1) 的空间复杂度。

突破口
假设 x 为重复元素,y 缺失元素

数组中所有元素 + 从 1 到 n 所有元素

以上所有元素中,x 出现 3 次,y 出现 1 次,其余均出现 2 次

以上所有元素进行异或运算,等价于 x ⊕ y x \oplus y xy

思路
第一步,计算 x ⊕ y x \oplus y xy,记为 xor
第二步,计算 x 和 y 的二进制表示中的最低不同位,记为 lowbit
第三步,把所有元素按照与 lowbit 进行与运算结果是否为 0 分成两组
第四步,每一组的元素都进行异或运算,最后得到两个数,num1 和 num2,一个重复,一个缺失
第五步,能在原数组中找到的数为重复,另一个是缺失的数

public int[] findErrorNums(int[] nums) {
        int n = nums.length;
        int xor = 0;
        // 数组中所有元素 进行异或 (一个缺失,一个重复)
        for (int num : nums) {xor ^= num;}
        // 1-n 进行异或 (缺失 1 次,重复 3 次,其余均为 2 次)
        for (int i = 1; i <= n; i++) {xor ^= i;}
        // lowbit 为 x 和 y 的二进制表示中的最低不同位
        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;}
        }
        // 此时 num1 和 num2 一个是 x,一个是 y
        // 遍历数组,如果能找到 num1 则 num1 为重复的数字,否则 num2 为重复的数字
        for (int num : nums) {if (num == num1) {return new int[]{num1, num2};
            }
        }
        return new int[]{num2, num1};
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值