![](/img/trans.png)
[英]Fastest way to check if exactly n items in a list match a condition in python
[英]fastest way to minimize n as per given condition in python
我怎样才能使以下代码更快? 输入是一个二进制字符串,我将其转换为数字。 可能我需要使用二进制字符串而不是数字? 该算法只能将其除以2或从输入中减去1。 我尝试了下面的代码,它不够快。
我尝试了以下方法:
def steps_to_zero(n) :
n=int(n,2)
count = 0
while n > 0:
if n % 2 == 0:
n = n // 2
else:
n = n - 1
count += 1
return (count)
它必须是此速度的两倍:
def steps_to_zero_v1(x):
x_int = int(x,2)
steps = 0
while x_int != 0:
if x_int % 2 == 0:
x_int = x_int // 2
else:
x_int = x_int - 1
steps += 1
return steps
您建议的代码与给定的代码完全相同。 您想要研究的主要问题是, if n % 2 == 0
测试,则摆脱昂贵的测试。
解决方案是,您可以在位级别上对此问题进行推理,而不必进行任何强力计算。
对于平凡的情况n=0
我们得到count=0
。 对于下一个更简单的情况, n=1
我们只需要减去1一次,导致count=1
。
在所有其他情况下,我们要处理更长的二进制数。 如果该数字的最后一位是0
,我们可以除以2以使我们的二进制数短一位:
...x0 / 2 = ...x # 1 step for 1 digit shorter
否则,我们必须先减去1,然后才能除以2。
...x1 - 1 = ...x0
...x0 / 2 = ...x # 2 steps for 1 digit shorter
换句话说:对于最左边的1,我们需要1运算,对于所有数字,如果它为0,则需要1;如果是1,则需要2。
这意味着您可以简单地通过计算字符串中1的数量来计算该值:
def steps_to_zero(n):
n = n.lstrip('0') # remove leading zeroes if they occur
divisions = len(n) - 1 # don't have to divide for the left-most 1
subtractions = n.count('1') # each 1 needs a subtraction to become a 0
return divisions + subtractions
% 2
和.count('1')
之间的时间比较平均在0-10,000之间:
# % 2
$ python3 -m timeit -s "x=list(range(10000))" "[y%2 for y in x]"
1000 loops, best of 3: 277 usec per loop
# .count('1')
$ python3 -m timeit -s "x=[bin(i) for i in range(10000)]" "[y.count('1') for y in x]"
1000 loops, best of 3: 1.35 msec per loop
虽然.count('1')
为〜5倍慢于%2
每次执行时, .count('1')
只需要执行一次,而%2
必须执行的log 2(N)次。 当n > 2**5 (=32)
时,这使.count('1')
方法更快。
无需将字符串转换为数字并执行昂贵的除法和模运算,只需一点一点地处理它即可。 除最左边的一位外,每1
位需要两步(减法和除法),而每一位0
位,则需要一步(除法):
def steps_to_zero(n):
count = 0
for x in n.lstrip('0'):
if x == '1':
count += 2
else:
count += 1
return count - 1
或者,如果您更喜欢单线:
def steps_to_zero(n):
return sum((x == '1') + 1 for x in n.lstrip('0')) - 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.