【每日题解】3226. 使两个整数相等的位更改次数

给你两个正整数 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。如果是其他情况的不相等则 changes+=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;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值