簡體   English   中英

如何優化此函數以返回給定范圍內具有唯一數字(即無重復數字)的整數數?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM