题目描述
Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.
例子
Example 1:
Input: 5
Output: 2
Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2.
Example 2:
Input: 1
Output: 0
Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0.
解释
给一个十进制的数字,返回他二进制表示的补码表示的十进制数。比如5,二进制101,补码010,十进制2,返回2。
思路
思路1 暴力解
把十进制数字的二进制表示先用一个string存下来,然后对string取补码(遍历,是1就变0,反之变1)。再把新的string变成十进制数字。
思路2 异或
对于二进制,一位数字和1异或等于取反,和0异或等于取同。所以由这个思路我们想到,把给定数字的每一位直接和1异或不就好了吗?没错,这个思路就是这么简单。但具体怎么操作呢?我们不需要把十进制数字转化成二进制数字然后一位一位异或,那样代价太大。我们只需要再有一个数字,它的每一位都是0,只有我们需要异或的那一位是1。这样的数字大家肯定不陌生:1,2,4,8…只要是2的整数幂,都有这样的性质,我们这里把这个数字叫做mask。所以我们从1开始,每次把mask和给定数字异或,之后将mask乘2(实现时对于*=2的操作,可以用<<=1来表示,即二进制移位,喜欢哪一种写法都可以),直到我们把每一位异或完,就大功告成了!
代码
暴力解代码
class Solution(object):
def findComplement(self, num):
"""
:type num: int
:rtype: int
"""
if num == 0:
return 1
#得到数字的二进制表示
str1 = ""
while num > 0:
print(num)
str1 = str(num % 2) + str1
num //= 2
#对二进制取补码
str2 = ""
for s in str1:
if s == '1':
str2 += '0'
else:
str2 += '1'
#用补码得到十进制
ans = 0
for i in range(len(str2)):
ans += int(str2[len(str2) - i - 1]) * (2 ** i)
return ans
异或代码
class Solution(object):
def findComplement(self, num):
"""
:type num: int
:rtype: int
"""
if num == 0:
return 1
#bit作为计数位,判断循环次数,即异或的位数
bit = num
#mask从1开始和num每一位异或
mask = 1
while bit:
num ^= mask #异或符号
bit >>= 1 #也可以写成bit //= 2
mask <<= 1 #也可以写成mask *= 2
return num