给你两个正整数 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
是最小的。
思路:
num & (num-1) 将num的最后一位1变成0
num | (num+1) 将num的最后一位0变成1
x的二进制表示中1的数目和num2相同,且要求x异或num1的值最小。
当x和num1相等时,异或的值最小,为0。
若num2中有k个1,那么“x异或num1的值最小”等价于————将num1中的k位反转(1变0,0变1)所得的最小值。
运用“贪心思想”,要让反转后的值最小,num1中高位的1就要变成0,如果k比num1中1的个数还多,那么就要让num1中低位的0变成1,这样得到的值最小。
直接在num1上进行改动,得到x:num1中1的个数为c1,num2中1的个数为c2,如果c1>c2,就将num1最低的c1-c2个1变成0;如果c1<c2,就将num1最低的c2-c1个0变成1。
class Solution {
public:
int minimizeXor(int num1, int num2) {
int num1Count=0;
int num2Count=0;
int temp1=num1;
int temp2=num2;
while(temp1)//num1中1的个数
{
temp1=temp1&(temp1-1);
num1Count++;
}
while(temp2)//num2中1的个数
{
temp2=temp2&(temp2-1);
num2Count++;
}
while(num1Count>num2Count)//如果c1>c2,就将num1最低的c1-c2个1变成0
{
num1=num1&(num1-1);
num2Count++;
}
while(num1Count<num2Count)//如果c1<c2,就将num1最低的c2-c1个0变成1
{
num1=num1|(num1+1);
num1Count++;
}
return num1;
}
};