题目描述
给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。
样例
输入: 5
输出: 2
解释: 5 的二进制表示为 101(没有前导零位),其补数为 010。所以你需要输出 2。
输入: 1
输出: 0
解释: 1 的二进制表示为 1(没有前导零位),其补数为 0。所以你需要输出 0。
说明
- 给定的整数保证在 32 位带符号整数的范围内。
- 你可以假定二进制数不包含前导零位。
- 本题与 1009 相同。
算法
(位运算) $O(\log n)$
- 此题的核心在于求出该数最高位 1 所代表的值,假设最高位的 1 在第
t
位上,则设tot = 1 << t
。最后答案为num
取反,然后取后t - 1
位,即按位与上tot - 1
。 - 可以采用枚举数位的方式,但题解中采用了求 lowbit 的方式。
- 注意特判输入为 0 的情况。
时间复杂度
- 最坏情况下需要遍历这个数的所有二进制位,故时间复杂度为 $O(\log n)$。
空间复杂度
- 仅需要常数的额外空间。
C++ 代码
class Solution {
public:
int findComplement(int num) {
if (!num) return 1;
int tot = 0;
for (int x = num; x; x -= x & -x)
tot = x;
return ~num & (tot - 1);
}
};
大佬,为什么时间复杂度是
O(logn)
呀?最坏情况是二进制位上全是 1,这时候
lowbit
会遍历所有的二进制位恩,那大佬像我是枚举数位,从
0~31
位挨个枚举,时间复杂度就是O(n)的吧。这样也是 $O(\log n)$ 的,只不过每次都需要 32 次遍历,常数会大。
大佬,按位与的意思是不是这样——
假如num是
5
,~num就是-6
,然后tot - 1
是3
。~num
的每一位和3
进行&
操作?对滴
大神能稍微解释一下吗
lowbit 是树状数组中的一个基本操作,其核心是让
x
按位与-x
,其中-x
就是x
所有位取反然后加 1。你可以手动试几个数字,理解一下 lowbit 操作。谢谢大佬回复!
做完上一个异或的题目,这个题目直接思路就是异或同样位数bit的1就可以了,感觉也不错hh
相对于1左移的方法,感觉这个比较intuition
为什么喜欢用lowbits的做法呢?