问题描述
小C在学习二进制运算,他了解到每个非负整数都有其二进制表示。例如,整数 5 可以被表示为二进制 "101",整数 11 可以被表示为二进制 "1011",并且除了 N = 0 外,任何二进制表示中都不含前导零。
二进制的反码表示是将每个 1 变为 0,每个 0 变为 1。例如,二进制数 "101" 的二进制反码为 "010"。现在小C想知道,给定一个十进制数 N,它的二进制反码对应的十进制数是多少。
测试样例
样例1:
输入:
N = 5
输出:2
样例2:
输入:
N = 10
输出:5
样例3:
输入:
N = 0
输出:1
解题思路
-
二进制长度:
- 二进制反码的掩码是一个所有位都为
1的数,长度与 N 的二进制位数相同。 - 计算 N 的二进制位数,用循环右移或位运算得到。
- 二进制反码的掩码是一个所有位都为
-
构造掩码:
- 使用位运算
(1 << len) - 1构造掩码,表示二进制位数为len的全1值。
- 使用位运算
-
计算反码:
- 使用掩码与 N 进行按位异或(XOR)计算反码:
mask ^ N。
- 使用掩码与 N 进行按位异或(XOR)计算反码:
-
特殊情况:
- 如果 N = 0,直接返回
1。
- 如果 N = 0,直接返回
Java代码实现
public class Main {
public static int solution(int N) {
if (N == 0) {
return 1;
}
int length = 0;
int temp = N;
while (temp > 0) {
length++;
temp >>= 1;
}
int mask = (1 << length) - 1;
return mask ^ N;
}
public static void main(String[] args) {
System.out.println(solution(5) == 2 ? 1 : 0);
System.out.println(solution(10) == 5 ? 1 : 0);
System.out.println(solution(0) == 1 ? 1 : 0);
}
}
解题步骤
-
特殊情况:
- 如果 N = 0,直接返回结果为
1。
- 如果 N = 0,直接返回结果为
-
二进制长度计算:
- 使用变量
length记录 N 的二进制长度,通过不断右移 N 直到为0,统计位数。
- 使用变量
-
构造掩码:
-
利用
(1 << length) - 1构造一个所有位都为1的掩码。例如:- 如果 N = 5,二进制长度为
3,掩码为111。
- 如果 N = 5,二进制长度为
-
-
计算反码:
-
通过
mask ^ N得到反码。例如:- N = 5,掩码为
111,二进制反码为111 ^ 101 = 010,对应十进制 2。
- N = 5,掩码为
-
-
返回结果:
- 输出计算得到的十进制结果。
复杂度分析
-
时间复杂度:
- 计算二进制长度的复杂度为 O(logN)(右移操作)。
- 总复杂度为 O(logN)。
-
空间复杂度:
- 只使用常量空间,复杂度为 O(1)。
总结
通过按位运算解决二进制反码问题具有高效性,特别是在位数较多时,构造掩码和异或操作的时间复杂度较低,适合大范围整数处理。该方法逻辑清晰、实现简单,且具有稳定的性能表现。