我需要编写一个函数来计算达到零的总步数。规则是
- 数字除以2
- 然后减去1
例如,如果我有14号
- 14/2 = 7
- 7-1 = 6
- 6/2 = 3
- 3-1 = 2
- 2/2 = 1
- 1-1 = 0
总步数为6
请注意,输入x是二进制字符串:
def test(x):
a = int(x,2)
steps = 0
while a != 0:
if a % 2 == 0:
a = a // 2
else:
a = a - 1
steps += 1
return steps
test("1000")
Out[65]: 4
test("101")
Out[66]: 4
test("001")
Out[67]: 1
test("0010010001")
Out[68]: 10
test("001001")
Out[69]: 5
我需要知道有什么方法可以编写快速的函数吗?
答案 0 :(得分:1)
假设您的代码正确且规则为:
需要注意的重要一点是:
因此,除第一个比特外的每个1位增加2步,而每个有效比特0则增加1个步。这意味着对于以1
开头的输入,您可以编写:
def test(x):
return x.count('1') + len(x) - 1
现在,您只需要考虑前导零,或者如果无法使用前导零,则只需考虑"0"
的特定情况。
答案 1 :(得分:0)
您的算法不适用于奇数。您只是在数字为偶数时进行除法,而这并不是您描述“步骤”的方式。
您想要的
def test(x, 2):
x_int = int(x)
steps = 0
while x_int <= 0:
x_int //= 2
x -= 1
steps += 1
您应该阐明算法,因为描述方式不保证所有输入都收敛为0。您描述的方式是一个奇数无限循环。只需尝试1:
#test(1)
1 // 2 = 0
0 - 1 = -1
...
现在您永远都不会达到0,这就是为什么您应该检查x_int <= 0的原因。
我建议您重新考虑为什么要这样做。我可以肯定地说,您甚至不需要迭代算法就可以知道需要多少“步骤”,为此应该只有一个数学公式。
答案 2 :(得分:0)
您还可以使用递归方法:
def stepsToZero(N):
return N if N < 2 else 2 + stepsToZero(N//2-1)
这将使您得到的结果达到N = 2 ** 993(这是一个很大的数字),并且功能非常简洁(imho更优雅)。
运行起来更快的是数学上的解决方法
例如:
import math
def steps2Zero(N):
if N < 2: return N
d = int(math.log(N+2,2))-1
s = int(N >= 3*2**d-2)
return 2*d+s
请注意,对于N = 2 ^ 900,数学解比递归快100倍。另一方面,递归函数在一秒钟内响应良好,并且可读性更高。因此,取决于使用方式和大小数字,性能考虑可能毫无意义