最小异或

标签: 贪心 位运算

难度: Medium

给你两个正整数 num1num2 ,找出满足下述条件的正整数 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 <= 109

Submission

运行时间: 23 ms

内存: 16.0 MB

class Solution:
    def minimizeXor(self, num1: int, num2: int) -> int:
        mask = 0
        c1 = num1.bit_count()
        c2 = num2.bit_count()
        while c2 < c1:
            num1 &= num1 - 1
            c1 -= 1
        while c2 > c1:
            num1 |= num1 + 1
            c2 -= 1
        return num1
        

Explain

该题解的核心思路是调整 num1 的二进制表示,使其包含的 1 的个数与 num2 相同,同时保持其值尽可能小。首先,计算 num1 和 num2 的二进制表示中 1 的个数(置位数),分别为 c1 和 c2。如果 num1 的置位数多于 num2(c1 > c2),则通过将 num1 与 (num1 - 1) 进行按位与操作去除最低位的 1 直到两者的置位数一致。如果 num1 的置位数少于 num2(c1 < c2),则通过将 num1 与 (num1 + 1) 进行按位或操作添加最低位的 0 直到置位数一致。这种方法保证了 num1 调整后的值是最小的符合条件的值。

时间复杂度: O(b)

空间复杂度: O(1)

class Solution:
    def minimizeXor(self, num1: int, num2: int) -> int:
        # 初始化mask为0
        mask = 0
        # 计算num1的置位数
        c1 = num1.bit_count()
        # 计算num2的置位数
        c2 = num2.bit_count()
        # 进行置位数减少,直到num1的置位数与num2相同
        while c2 < c1:
            num1 &= num1 - 1
            c1 -= 1
        # 进行置位数增加,直到num1的置位数与num2相同
        while c2 > c1:
            num1 |= num1 + 1
            c2 -= 1
        # 返回调整后的num1
        return num1

Explore

在二进制表示中,num1与(num1 - 1)进行按位与操作的效果是将num1的最低位的1变为0,并且保持该位之后的所有位不变。这是因为从二进制的角度看,如果num1的某位是1,那么从这一位到最右端的所有位在num1-1中都会变成0,并且这一位会变成0。因此,num1与(num1 - 1)的按位与操作,实际上是把num1的最低位的1和之后的所有0变成了0,达到了去除最低位1的目的。

当我们将num1与(num1 + 1)进行按位或操作时,操作的效果是在num1的最低位的0之前添加一个1。这是因为num1的二进制表示中最低位的0,在num1+1中会变成1,而num1中所有低于这个位的1会在num1+1中变成0然后再变回1(由于进位)。因此,num1与(num1 + 1)的按位或结果是在原来的num1基础上在最低的0位转变为1,这确保了只增加一个1位。

在调整置位数的操作中,通过选择性地去除最低位的1或添加到最低位的0,我们优先保留了较高位的1,这样可以保证数值尽可能小。例如,去除较高位的1会导致数值减小更多,而我们的操作避免了这一点,只去除或添加最低位的。因此,通过这种方式调整num1,可以确保在满足置位数与num2相同的前提下,num1的数值是最小可能的,这就保证了num1是最小的符合条件的值。