2997. 使数组异或和等于 K 的最少操作次数
题目
给你一个下标从 0 开始的整数数组 nums
和一个正整数 k
。
你可以对数组执行以下操作 任意次 :
- 选择数组里的 任意 一个元素,并将它的 二进制 表示 翻转 一个数位,翻转数位表示将
0
变成1
或者将1
变成0
。
你的目标是让数组里 所有 元素的按位异或和得到 k
,请你返回达成这一目标的 最少 操作次数。
注意,你也可以将一个数的前导 0 翻转。比方说,数字 (101)2
翻转第四个数位,得到 (1101)2
。
示例 1:
输入:nums = [2,1,3,4], k = 1
输出:2
解释:我们可以执行以下操作:
- 选择下标为 2 的元素,也就是 3 == (011)2 ,我们翻转第一个数位得到 (010)2 == 2 。数组变为 [2,1,2,4] 。
- 选择下标为 0 的元素,也就是 2 == (010)2 ,我们翻转第三个数位得到 (110)2 == 6 。数组变为 [6,1,2,4] 。
最终数组的所有元素异或和为 (6 XOR 1 XOR 2 XOR 4) == 1 == k 。
无法用少于 2 次操作得到异或和等于 k 。
示例 2:
输入:nums = [2,0,2,0], k = 0
输出:0
解释:数组所有元素的异或和为 (2 XOR 0 XOR 2 XOR 0) == 0 == k 。所以不需要进行任何操作。
提示:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^6
0 <= k <= 10^6
解答
比特位翻转在位与位之间是互不干扰的,因此只需要统计异或和与 k
之间相差多少个 1,也就是再异或一次,看里面有多少 1.
python
class Solution:
def minOperations(self, nums: List[int], k: int) -> int:
for x in nums:
k ^= x
return k.bit_count()
bit_count()
方法
- 计算二进制中 置位个数 的数,Python 3.10 引入
x.bit_count()
int.bit_count(x)
int
还有一些方法:
as_integer_ratio
:将一个整数表示成分子和分母的比值形式。它返回一个元组,其中包含两个整数,分别表示分子和分母,不知道为啥,有时候很大bit_count
:bit_length
:返回一个整数的二进制表示的 位数 的方法conjugate
:返回一个具有虚部符号相反的复数imag
real
denominator
:Fraction
类的实例的属性numerator
:同上from_bytes
:把bytes
类型的变量x
,转化为十进制整数to_bytes
似乎都没啥用。
C++ 中的 bit_count()
类似的函数有:__builtin_popcount(args)
,具体的可以看:
- 这是一个 gcc 内建的函数,似乎用了二分
- Is builtinpopcount O(1) or O(log_2 k) ? - Codeforces
- 分享|从集合论到位运算,常见位运算技巧分类总结! - 力扣(LeetCode)
C++ 代码:
cpp
// https://space.bilibili.com/206214
auto init_ = [] {
cin.tie(nullptr)->sync_with_stdio(false);
return 0;
}();
class Solution {
public:
int minOperations(vector<int> &nums, int k) {
for (int x : nums) {
k ^= x;
}
return __builtin_popcount(k);
}
};
如果要自己手写的话:
cpp
class Solution {
public:
int minOperations(vector<int>& nums, int k) {
for (int x : nums) {
k ^= x;
}
int cnt = 0;
while (k) {
if (k & 1) {
cnt ++;
}
k >>= 1;
}
return cnt;
}
};
其实可以复习一下 位运算 的两个算法:
x & 1
看末位是 0 还是 1lowbit(x) = x & -x
返回x
的最后一位1
以及后面的0
cpp
class Solution {
public:
int lowbit(int x) {
return x & -x;
}
int minOperations(vector<int>& nums, int k) {
for (int x : nums) {
k ^= x;
}
int cnt = 0;
while (k) {
k -= lowbit(k);
cnt ++;
}
return cnt;
}
};