面试题 17.19. 消失的两个数字(妙用异或)

给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?

以任意顺序返回这两个数字均可。

示例 1:
输入: [1]
输出: [2,3]
示例 2:
输入: [2,3]
输出: [1,4]
提示:
nums.length <= 30000

解题思路

数学思考
因为知道1~n的所有整数,然后给出已有的n-2个数,很容易就能想到将这n-2个数异或,与1~n的异或就差了缺的俩数x = x1^x2异或值
那么重要的点来,如何利用x1^x2来分别得到x1,x2?

  • Key1: 一堆已知的数中只缺一个数的话可以通过异或得到
  • Key2: 利用x1和x2特征区别将数分为两类:
    • 通过x&(-x)即可得到x1^x2异或值中的一个二进制第i位的1,那么这个1意味着x1和x2在该二进制位不同才会异或得到1
    • 对1~n的数通过第i位值划分为两类,对nums也划分为两类
    • 有了x1 和 x2分别属于两类,如此通过Key1可以找到x1,x2

代码

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        int x = 0;
        int n = nums.size()+2;
        // 将1~n和nums异或起来,得到缺的两个数字异或值x=x1^x2
        while(n) x ^= n, n--;
        for(int i = 0; i < nums.size(); i++) x ^= nums[i];
        // 找到二进制中x1 和 x2异或值为1的一个位置,说明此位置上两数不同
        int flag = x&(-x); // 得到的是x1与x2异或值为1的最低位

        // 找到1~n此位置为1的数异或得到一个值y1,找到nums中此位置为1的数异或得到一个值y2,这俩异或值的区别就是x1的参与,y1^y2=x1
        // 同理看此位置为0的异或值,得到x2
        int y1 = 0, y2 = 0;
        int y3 = 0, y4 = 0;
        n = nums.size()+2;
        while(n){
            if(n&flag) y1^=n;
            else y3^=n;
            n--;
        }
        for(int i = 0; i < nums.size(); i++){
            if(nums[i]&flag) y2^=nums[i];
            else y4^=nums[i];
        }
        return {y1^y2,y3^y4};
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AlwaysDayOne

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值