1318-或运算的最小翻转次数
给你三个正整数 a、b 和 c。
你可以对 a 和 b 的二进制表示进行位翻转操作,返回能够使按位或运算 a OR b == c 成立的最小翻转次数。
「位翻转操作」是指将一个数的二进制表示任何单个位上的 1 变成 0 或者 0 变成 1 。
示例 1:

**输入:** a = 2, b = 6, c = 5
**输出:** 3
**解释:** 翻转后 a = 1 , b = 4 , c = 5 使得 a OR b == c
示例 2:
**输入:** a = 4, b = 2, c = 7
**输出:** 1
示例 3:
**输入:** a = 1, b = 2, c = 3
**输出:** 0
提示:
1 <= a <= 10^91 <= b <= 10^91 <= c <= 10^9
预备知识
本题需要用到一些位运算的知识:
对于十进制整数
x,我们可以用x & 1得到x的二进制表示的最低位,它等价于x % 2:例如当
x = 3时,x的二进制表示为11,x & 1的值为1;例如当
x = 6时,x的二进制表示为110,x & 1的值为0。
对于十进制整数
x,我们可以用x & (1 << k)来判断x二进制表示的第k位(最低位为第0位)是否为1。如果该表达式的值大于零,那么第k位为1:例如当
x = 3时,x的二进制表示为11,x & (1 << 1) = 11 & 10 = 10 > 0,说明第1位为1;例如当
x = 5时,x的二进制表示为101,x & (1 << 1) = 101 & 10 = 0,说明第1位不为1。
对于十进制整数
x,我们可以用(x >> k) & 1得到x二进制表示的第k位(最低位为第0位)。如果x二进制表示的位数小于k,那么该表达式的值为零:例如当
x = 3时,x的二进制表示为11,(x >> 1) & 1 = 1 & 1 = 1,说明第1位为1;例如当
x = 5时,x的二进制表示为101,(x >> 1) & 1 = 10 & 1 = 0,说明第1位为0。例如当
x = 6时,x的二进制表示为110,(x >> 3) & 1 = 0 & 1 = 0,说明第3位为0。
方法一:枚举 + 位运算
由于在或(OR)运算中,二进制表示的每一位都是独立的,即修改 a 或 b 二进制表示中的第 i 位,只会影响 a OR b 中第 i 位的值,因此我们可以依次枚举并考虑每一位。注意到 a、b 和 c 均小于 10^9,它们的二进制表示最多有 30 位(包含 31 个二进制位的数最小为 2^30 = 1073741824,已经大于 10^9),因此我们只需要从低位到高位枚举这 30 位即可。
设 a、b 和 c 二进制表示的第 i 位分别为 bit_a、bit_b 和 bit_c,根据 bit_c 的值,会有以下两种情况:
若
bit_c的值为0,那么bit_a和bit_b必须都为0,需要的翻转次数为bit_a + bit_b;若
bit_c的值为1,那么bit_a和bit_b中至少有一个为1,只有当它们都为0时,才需要1次翻转;
我们将每一位的翻转次数进行累加,在枚举完所有位之后,就得到了最小翻转次数。
1 | class Solution { |
1 | class Solution: |
复杂度分析
时间复杂度:O(\log C),其中
C为常数,在本题中,C的值为 10^9。O(\log C) 等价于C的位数,也就是我们需要枚举的位数。空间复杂度:O(1)。