第496题 负二进制表示问题
题目分析
题目要求将一个整数 nnn 转换为负二进制(基数为 -2)的形式,并返回其对应的二进制字符串。
在普通的二进制表示中,基数是 2,即每一位上的权值是 2i2^i2i。但是在负二进制表示中,基数是 -2,这意味着每一位上的权值是 (−2)i(-2)^i(−2)i(即交替的正负数)。因此,负二进制的表示方式与普通二进制不同,其在转换过程中有特殊的规则,尤其是在计算余数时,需要进行额外的调整。
解题思路
-
基本理解:
- 负二进制表示是基数为 -2 的表示法。每一位的权值是 (−2)i(-2)^i(−2)i。
- 例如,对于 n=2n = 2n=2,其负二进制表示应为 "110",因为 2=(−2)2+(−2)1+(−2)02 = (-2)^2 + (-2)^1 + (-2)^02=(−2)2+(−2)1+(−2)0,即 2=4−2+02 = 4 - 2 + 02=4−2+0。
-
计算方法:
-
我们使用 除法取余 的方法来转换数字:
- 每次将数字 nnn 除以 -2,得到商和余数。
- 余数应始终保持非负(0 或 1),如果余数为负,则需要调整。调整的方法是将余数加 2,同时商增加 1。
-
重复这个过程,直到商为 0。
-
最后,将所有余数反向排列,即可得到负二进制表示。
-
-
特殊情况:
- 如果 n=0n = 0n=0,直接返回 "0"。
解题代码
def solution(n: int) -> str:
if n == 0:
return "0"
result = []
while n != 0:
n, remainder = divmod(n, -2)
# 处理负余数
if remainder < 0:
remainder += 2
n += 1
result.append(str(remainder))
return ''.join(result[::-1]) # 反转结果并返回
if __name__ == '__main__':
print(solution(n=2) == '110')
print(solution(n=3) == '111')
print(solution(n=0) == '0')
模块解释
-
divmod(n, -2):divmod是 Python 内置的函数,它返回两个数相除后的商和余数。用它来计算负二进制时,商是 nnn 除以 -2 的商,余数是 nnn 除以 -2 的余数。- 在负二进制的情况下,余数的范围应为 0 或 1。如果余数为负,我们通过调整来保证余数非负。
-
余数调整:
-
如果余数小于 0(即为 -1),我们需要做调整:
- 将余数加 2 使其变为正数。
- 同时商增加 1(因为我们修改了余数,商应向上取整)。
-
-
result.append(str(remainder)):- 每次计算出余数后,我们将其加入结果列表
result中,最终得到反向的负二进制表示。
- 每次计算出余数后,我们将其加入结果列表
-
''.join(result[::-1]):- 由于我们从最低位开始计算余数,结果列表中的余数是从低位到高位排列的,所以需要反转列表来得到正确的负二进制表示。
结论
-
时间复杂度:O(log|n|),每次操作都会将 nnn 减少一半,因此转换过程的时间复杂度是对数级别的,即与数字的大小的对数成正比。
-
空间复杂度:O(log|n|),我们需要一个结果列表来存储转换过程中每个余数。由于最多需要进行对数次计算,因此空间复杂度是对数级别的。