[英]How can I optimize this function to return the number of integers with unique digits (ie. no repeating digits) in a given range?
给定两个整数的列表(即[1,20]或[10,10000]),我正在尝试创建一个函数,该函数返回不包含重复数字(即。 8、9、10会计数,但11不会)。 当输入列表相对较小时,我在此处编写的代码可以正常工作,但在范围较大时,效率较低。 如何提高效率?
good_numbers = 0
current_count = list[0]
while current_count <= list[1]:
list_of_digits = [int(i) for i in str(current_count)]
if len(list_of_digits) == len(set(list_of_digits)):
good_numbers += 1
current_count += 1
print(good_numbers)
当范围相对较小时,此方法效果很好,但是当范围较大时,我会收到超时错误。
在不更改算法的情况下,速度提高了约3倍
In [38]: def a(start, end):
...: g = 0
...: for i in range(start, end+1):
...: s = list(f"{i}")
...: if len(s) == len(set(s)):
...: g += 1
...: return g
...:
结果:
New
In [35]: %timeit a(10, 10000)
12.1 ms ± 147 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Yours :
In [37]: %timeit b([10, 10000])
33.5 ms ± 402 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
编辑:
对于überfaster解决方案,您需要更智能一点。
例如:基本上,您需要能够找到开始和结束边界之间的数字排列。
假设您没有边界。 该操作将简单地计算n位,n -1位,n-2位的排列数的总和...
例如,如果我有3位数字,则我需要总和为9 +(9 * 9)+(9 * 9 * 8)(尝试使用我或您的边界为1,1000的代码进行此操作:)
哪里,
In [80]: %timeit 9 + 9 * 9 + 9 * 9 * 8
11.2 ns ± 0.13 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
您需要提出一种算法,例如
In [89]: from functools import reduce
In [90]: def c(start, end):
...: sl = len(list(f"{start}"))
...: el = len(list(f"{end}"))
...: t = 0
...: for i in range(sl, el):
...: t += reduce(lambda x, y: x * y, [9 - j for j in range(i - 1)], 9)
...: return t
In [91]: %timeit c(10, 10000)
7.93 µs ± 46.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
但这缺少边界值的控制,您需要检查边界值是否大于开始值和小于结束值。
如您所见,最后一个速度快了1400倍:D但缺少您需要应用的必要控件
如果您知道n位数字的数量与排列数量相同而无需重复10个元素,而我们只选择n个元素,再乘以9/10(以去除那些从零开始),其中n> = 2
例如:
用2位数-> 10! / 8! * 9/10 = 81
3位数字-> 10! / 7! * 9/10 = 648
n = 1是一种特殊情况(如果包含零,我们可以用1位数字做10个可能的数字)
现在,您可以计算出最多包含n位非重复数字的数字量,如下所示:
n = 1-> 10
n = 2-> 10 + 81 = 91
n = 3-> 10 + 81 + 739 + 4536
...
这是一个计算它的简单函数:
from functools import reduce
from operator import mul
@lru_cache(maxsize=32)
def good_numbers(n):
if n > 10:
return good_numbers(10)
if n == 1:
return 10
return good_numbers(n - 1) + 9 * reduce(mul, range(10 - n + 1, 10))
print([good_numbers(k) for k in range(1, 5)])
输出为:
[10, 91, 739, 5275]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.