如何增强以下代码的性能?

时间:2018-01-16 04:07:57

标签: python algorithm

该功能的目标和条件如下:

目标
1.所有这些数字的总数,它的总和是数字== sum_dig
2.它自己的数字总和的最小值== sum_dig
3.它自己的数字之和的最大数量== sum_dig

条件
4.数字必须按递增顺序排列
5.位数== digs


例如
find_all(10, 3)应该返回[8,118,334]
find_all(27, 3)应该返回[1,999,999]
find_all(84, 4)应该返回[]
find_all(35, 6)应返回[123,116999,566666]

P.S。对不起,如果有任何问题,我是新来的代码,请让我知道^^ Thx提前!

def find_all(sum_dig, digs):
    ls = set(n for n in set(''.join(sorted(str(i))) for i in range(int('1'*digs),int('9'*digs)+1) if '0' not in str(i)) if sum(int(i) for i in n) == sum_dig)
    if len(ls) ==0:
        return []
    return [len(ls),int(min(ls)),int(max(ls))]

可读版本

def find_all(sum_dig, digs):
    #find int in increasing order within range
    ls = set(''.join(sorted(str(i))) for i in range(int('1'*digs),int('9'*digs)+1))
    #find sum of it's digi == sum_dig within min. list 
    ls = set(n for n in ls if '0' not in n and sum(int(i) for i in n) == sum_dig)
    if len(ls) ==0:
        return []
    return [len(ls),int(min(ls)),int(max(ls))]

1 个答案:

答案 0 :(得分:0)

这是另一种强大技术branch-and-bound的例子。一般的想法是,如果我们将数字中的第一个数字修改为i,我们可以将此任务减少到find_all(sum_digi-i, digits-1)。此外,我们可以对搜索空间进行大量修剪,因为我们知道可行sum_digi属于[digits*min_digit, 9*digits],其中min_digit是前缀中的最大数字(数字按递增顺序排列)。其余的只是结合最小和最大:

def find_all(sum_digi, digits, min_digit=1):
     grand_total = 0
     super_min = 10**digits-1
     super_max = 0
     if digits == 1:
         if min_digit <= sum_digi <= 9:
             return 1, sum_digi, sum_digi
     elif digits > 1: 
         for i in range(min_digit, 10):
             if (digits-1)* min_digit <= sum_digi -i <= 9*(digits-1):
                 total, n_min, n_max = find_all(sum_digi - i, digits-1, i)
                 if total:
                     grand_total += total
                     super_min = min(super_min, 10**(digits-1)*i+n_min)
                     super_max = max(super_max, 10**(digits-1)*i+n_max)
     return grand_total, super_min, super_max

性能:

In [4]: %%time
   ...: find_all(100, 20)
   ...: 
CPU times: user 380 ms, sys: 12 ms, total: 392 ms
Wall time: 384 ms
Out[4]: (61731, 11111111119999999999L, 55555555555555555555L)