题目

2997. 使数组异或和等于 K 的最少操作次数 - 力扣(LeetCode)

给你一个下标从 0 开始的整数数组 nums 和一个正整数 k

你可以对数组执行以下操作 任意次

  • 选择数组里的 任意 一个元素,并将它的 二进制 表示 翻转 一个数位,翻转数位表示将 0 变成 1 或者将 1 变成 0

你的目标是让数组里 所有 元素的按位异或和得到 k ,请你返回达成这一目标的 最少 操作次数。

注意,你也可以将一个数的前导 0 翻转。比方说,数字 (101)2 翻转第四个数位,得到 (1101)2

示例 1:

1
2
3
4
5
6
7
输入: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:

1
2
3
输入: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
1
2
3
4
5
class Solution {
public int minOperations(int[] nums, int k) {

}
}

解题

让数组nums所有元素的按位异或后的结果,我们设为 res

res等于k,等价于二者异或后为0。因为对于异或操作来说,两个相同的数异或,结果为0。

因此我们可以让resk进行异或得到ans,然后看看ans中有几个1,我们将这些1翻转为0即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
// 计算给定数字的二进制表示形式中 1 的数量,也可以调用Integer.bitCount()方法
public int getOneCount(int n) {
int count = 0;
while(n > 0) {
n &= n-1;
count++;
}
return count;
}

public int minOperations(int[] nums, int k) {
int res = 0;
for(int x : nums) {
res ^= x;
}
int ans = res ^ k;
return getOneCount(ans);
}
}