给你两个正整数 n
和 k
。
你可以选择 n
的 二进制表示 中任意一个值为 1 的位,并将其改为 0。
返回使得 n
等于 k
所需要的更改次数。如果无法实现,返回 -1。
示例 1:
输入: n = 13, k = 4
输出: 2
解释:
最初,n
和 k
的二进制表示分别为 n = (1101)2
和 k = (0100)2
,
我们可以改变 n
的第一位和第四位。结果整数为 n = (0100)2 = k
。
示例 2:
输入: n = 21, k = 21
输出: 0
解释:n
和 k
已经相等,因此不需要更改。
示例 3:
输入: n = 14, k = 13
输出: -1
解释:
无法使 n
等于 k
。
思路
先看二进制的长度,如果 k 的二进制数的长度大于 n 的二进制数,则不可能。然后按位比较即可,注意只能把 n 中的 1 变成 0。所以如果 n 中某一位是 0 但是 k 中这一位是 1 则返回 -1。如果是其他情况的不相等则
二进制操作
len(bin(x))-2 # bin(x) 在python中返回二进制表达 3 -> 0b11
-
bin(x)
将整数x
转换为二进制字符串,例如bin(13)
返回'0b1101'
。
while (x > 0) { x >>= 1; length++}
-
x >>= 1
将x
右移一位,相当于x = x / 2
。
n & 1 和 k & 1
-
n & 1
和k & 1
用于检查n
和k
的最低位(最右边的一位)。 -
&
是按位与操作符,n & 1
的结果是n
的最低位。 -
例如,如果
n = 13
(二进制1101
),n & 1
的结果是1
,因为1101 & 0001 = 0001
。
n >>= 1 和 k >>= 1
-
n >>= 1
和k >>= 1
将n
和k
右移一位,相当于n = n / 2
和k = k / 2
。 -
右移操作会丢弃最低位,并将所有位向右移动一位。
-
例如,如果
n = 13
(二进制1101
),n >>= 1
后n
变为6
(二进制0110
)。
代码(Python)
class Solution:
def minChanges(self, n: int, k: int) -> int:
def bit_length(x):
return len(bin(x)) - 2
if bit_length(n) < bit_length(k):
return -1
changes = 0
while n > 0 or k > 0:
if (n & 1) == 0 and (k & 1) == 1:
return -1
if (n & 1) != (k & 1):
changes += 1
n >>= 1
k >>= 1
return changes
代码(C++)
class Solution {
public:
int count_length(int x) {
int count = 0;
while (x > 0) {
x >>= 1;
count++;
}
return count;
}
int minChanges(int n, int k) {
int changes = 0;
if (count_length(k) > count_length(n)) return -1;
while (n > 0 || k > 0) {
if ((n & 1) == 0 && (k & 1) == 1) {
return -1;
} else if ((n & 1) != (k & 1)) {
changes++;
}
n >>= 1;
k >>= 1;
}
return changes;
}
};