最小 XOR

163 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

🎈算法并不一定都是很难的题目,也有很多只是一些代码技巧,多进行一些算法题目的练习,可以帮助我们开阔解题思路,提升我们的逻辑思维能力,也可以将一些算法思维结合到业务代码的编写思考中。简而言之,平时进行的算法习题练习带给我们的好处一定是不少的,所以让我们一起来养成算法练习的习惯。今天练习的题目是一道中等难度的题目 -> 最小 XOR

题目描述

给你两个正整数 num1 和 num2 ,找出满足下述条件的整数 x :

x 的置位数和 num2 相同,且 x XOR num1 的值 最小 注意 XOR 是按位异或运算。

返回整数 x 。题目保证,对于生成的测试用例, x 是 唯一确定 的。

整数的 置位数 是其二进制表示中 1 的数目。

示例 1:

输入:num1 = 3, num2 = 5
输出:3
解释:
num1 和 num2 的二进制表示分别是 0011 和 0101 。
整数 3 的置位数与 num2 相同,且 3 XOR 3 = 0 是最小的。

示例 2:

输入:num1 = 1, num2 = 12
输出:3
解释:
num1 和 num2 的二进制表示分别是 0001 和 1100 。
整数 3 的置位数与 num2 相同,且 3 XOR 1 = 2 是最小的。

提示:

  • 1 <= num1, num2 <= 10^9

思路分析

首先我们要先理解一下题目的意思,题目会给我们两个正整数num1num2,要求我们通过这两个正整数求得一个整数x,整数x应该满足以下两个条件:

  • x 的置位数和 num2 相同,整数的 置位数 是其二进制表示中 1 的数目
  • x XOR num1 的值 最小XOR 是按位异或运算

异或运算

首先我们应该先了解一下什么是异或运算及异或运算规则
异或是一个数学运算符。它应用于逻辑运算。异或的数学符号为“⊕”,计算机符号为“xor”。
其中:真⊕假=真,假⊕真=真,假⊕假=假,真⊕真=假(二进制下用1表示真,0表示假)

解题步骤

  • 1、计算num2的置位数n
let n = 0;
 for(let i = 0; i < num2.length; i++){
     n += parseInt(num2[i]);
 }
  • 2、找出置位数为n,且与num1异或值最小的x (1)初始化xx的位数应该为num1的位数和置位数n之间的最大值
let x = new Array(Math.max(num1.length,n)).fill(0);

(2)因为异或运算中1 XOR 1 = 0,所以我们只需要从高位向低位遍历,遇到num1中二进制位为1时,x在该位数也补1,并且消耗一个置位数

for(let i = 0;i < num1.length && n > 0; i++){
    //x在该位数也补`1`
    x[i] = num1[i];
    //消耗一个置位数
    n -= parseInt(num1[i]);
}

(3)如果置位数未消耗完,我们需要继续在x中补1,这时要使x XOR num1 的值 最小,我们应该优先在低位补1

let len = x.length - 1;
while(n){
    while(x[len] == '1' || num1[len] == '1') len--;
    if(len < 0) break;
    x[len] = '1';
    n--
}

(4)二进制转换为10进制

return parseInt(x.join(''),2);

AC代码

/**
 * @param {number} num1
 * @param {number} num2
 * @return {number}
 */
 var minimizeXor = function(num1, num2) {
    num2 = num2.toString(2);
    num1 = num1.toString(2);
    let n = 0;
    for(let i = 0; i < num2.length; i++){
        n += parseInt(num2[i]);
    }
    let x = new Array(Math.max(num1.length,n)).fill(0);
    for(let i = 0;i < num1.length && n > 0; i++){
        x[i] = num1[i];
        n -= parseInt(num1[i]);
    }
    let len = x.length - 1;
    while(n){
        while(x[len] == '1' || num1[len] == '1') len--;
        if(len < 0) break;
        x[len] = '1';
        n--
    }
    return parseInt(x.join(''),2);
};

说在后面

🎉这里是JYeontu,喜欢算法,GDCPC打过卡;热爱羽毛球,大运会打过酱油。毕业一年,两年前端开发经验,目前担任H5前端开发,算法业余爱好者,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。