
题目描述
给你两个正整数 num1 和 num2 ,找出满足下述条件的正整数 x :
x 的置位数和 num2 相同,且 x XOR num1 的值 最小
注意 XOR 是按位异或运算。
返回整数 x 。题目保证,对于生成的测试用例, x 是 唯一确定 的。
整数的 置位数 是其二进制表示中 1 的数目。
示例 1:
输入:num1 = 3, num2 = 5
输出:3
解释:
num1 和 num2 的二进制表示分别是 0011 和 0101 。
整数 3 的置位数与 num2 相同,且 3 XOR 3 = 0 是最小的。
示例 2:
输入:num1 = 1, num2 = 12
输出:3
解释:
num1 和 num2 的二进制表示分别是 0001 和 1100 。
整数 3 的置位数与 num2 相同,且 3 XOR 1 = 2 是最小的。
提示:
解法
方法一:贪心 + 位运算
根据题目描述,我们先求出 \(\textit{nums2}\) 的置位数 \(\textit{cnt}\),然后从高位到低位枚举 \(\textit{num1}\) 的每一位,如果该位为 \(1\),则将 \(x\) 的对应位设为 \(1\),并将 \(\textit{cnt}\) 减 \(1\),直到 \(\textit{cnt}\) 为 \(0\)。如果此时 \(\textit{cnt}\) 仍不为 \(0\),则从低位开始将 \(\textit{num1}\) 的每一位为 \(0\) 的位置设为 \(1\),并将 \(\textit{cnt}\) 减 \(1\),直到 \(\textit{cnt}\) 为 \(0\)。
时间复杂度 \(O(\log n)\),其中 \(n\) 为 \(\textit{num1}\) 和 \(\textit{num2}\) 的最大值。空间复杂度 \(O(1)\)。
1
2
3
4
5
6
7
8
9
10
11
12
13 | class Solution:
def minimizeXor(self, num1: int, num2: int) -> int:
cnt = num2.bit_count()
x = 0
for i in range(30, -1, -1):
if num1 >> i & 1 and cnt:
x |= 1 << i
cnt -= 1
for i in range(30):
if num1 >> i & 1 ^ 1 and cnt:
x |= 1 << i
cnt -= 1
return x
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | class Solution {
public int minimizeXor(int num1, int num2) {
int cnt = Integer.bitCount(num2);
int x = 0;
for (int i = 30; i >= 0 && cnt > 0; --i) {
if ((num1 >> i & 1) == 1) {
x |= 1 << i;
--cnt;
}
}
for (int i = 0; cnt > 0; ++i) {
if ((num1 >> i & 1) == 0) {
x |= 1 << i;
--cnt;
}
}
return x;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | class Solution {
public:
int minimizeXor(int num1, int num2) {
int cnt = __builtin_popcount(num2);
int x = 0;
for (int i = 30; ~i && cnt; --i) {
if (num1 >> i & 1) {
x |= 1 << i;
--cnt;
}
}
for (int i = 0; cnt; ++i) {
if (num1 >> i & 1 ^ 1) {
x |= 1 << i;
--cnt;
}
}
return x;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | func minimizeXor(num1 int, num2 int) int {
cnt := bits.OnesCount(uint(num2))
x := 0
for i := 30; i >= 0 && cnt > 0; i-- {
if num1>>i&1 == 1 {
x |= 1 << i
cnt--
}
}
for i := 0; cnt > 0; i++ {
if num1>>i&1 == 0 {
x |= 1 << i
cnt--
}
}
return x
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | function minimizeXor(num1: number, num2: number): number {
let cnt = 0;
while (num2) {
num2 &= num2 - 1;
++cnt;
}
let x = 0;
for (let i = 30; i >= 0 && cnt > 0; --i) {
if ((num1 >> i) & 1) {
x |= 1 << i;
--cnt;
}
}
for (let i = 0; cnt > 0; ++i) {
if (!((num1 >> i) & 1)) {
x |= 1 << i;
--cnt;
}
}
return x;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | impl Solution {
pub fn minimize_xor(num1: i32, mut num2: i32) -> i32 {
let mut cnt = 0;
while num2 > 0 {
num2 -= num2 & -num2;
cnt += 1;
}
let mut x = 0;
let mut c = cnt;
for i in (0..=30).rev() {
if c > 0 && (num1 >> i) & 1 == 1 {
x |= 1 << i;
c -= 1;
}
}
for i in 0..=30 {
if c == 0 {
break;
}
if ((num1 >> i) & 1) == 0 {
x |= 1 << i;
c -= 1;
}
}
x
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | public class Solution {
public int MinimizeXor(int num1, int num2) {
int cnt = BitOperations.PopCount((uint)num2);
int x = 0;
for (int i = 30; i >= 0 && cnt > 0; --i) {
if (((num1 >> i) & 1) == 1) {
x |= 1 << i;
--cnt;
}
}
for (int i = 0; cnt > 0; ++i) {
if (((num1 >> i) & 1) == 0) {
x |= 1 << i;
--cnt;
}
}
return x;
}
}
|