Python 我的程序需要很长时间才能打印出25个以上的结果,有没有办法在运行时提高效率?

Python 我的程序需要很长时间才能打印出25个以上的结果,有没有办法在运行时提高效率?,python,math,python-3.6,Python,Math,Python 3.6,这些是我正在使用的行,它生成了一个列表,列出了输入的整数和的可能组合,然后说明了组合的数量 import itertools val = int(input()) r = range(val)[1:] res = [] for i in range(len(r)+1): res += [list(x) for x in itertools.combinations(r, i) if sum(list(x)) == val] print("Solution : %s "

这些是我正在使用的行,它生成了一个列表,列出了输入的整数和的可能组合,然后说明了组合的数量

import itertools

val = int(input())
r = range(val)[1:]
res = []    
for i in range(len(r)+1):
    res += [list(x) for x in itertools.combinations(r, i) if sum(list(x)) == val]    
print("Solution : %s " % res)
print("Combinations : %s" % len(res))

看起来您正在计算每个可能的组合,然后只保留满足求和条件的组合。它正在搜索的组合池以2^(n-1)的速度增长,您可以通过注释掉条件部分看到:

import itertools
import time

startTime = time.time()

val = 21
r = range(val)[1:]
res = []    
for i in range(len(r)+1):
    res += [list(x) for x in itertools.combinations(r, i)]# if sum(list(x)) == val]    
#print("Solution : %s " % res)
print("Combinations : %s" % len(res))

print(time.time() - startTime, 'seconds')
试试这个:

def a(lst, target, with_replacement=False):
    def _a(idx, l, r, t, w):
        if t == sum(l): r.append(l)
        elif t < sum(l): return
        for u in range(idx, len(lst)):
            _a(u if w else (u + 1), l + [lst[u]], r, t, w)
        return r
    return _a(0, [], [], target, with_replacement)

val = 50
s = range(1, val)
solutions = a(s, val)
print(solutions)
print(len(solutions))
上述方法:

val = 24, t = 0.0084612369537353 seconds
val = 25, t = 0.0069310665130615 seconds
val = 26, t = 0.0085859298706054 seconds
val = 50, t = 0.4947729110717773 seconds

可能有很多方法可以提高速度。我尝试了一个简单的方法(并注意到这有很大的不同):消除生成器和列表之间的重复转换。这是您的代码,已修改:

import time
import itertools

#val = int(input("val:"))
#r = range(val)[1:]

def simple_time_func(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        r = func(*args, **kwargs)
        print("{} took {:.3f} seconds.".format(func.__name__, time.time() - start))
        return r
    return wrapper

@simple_time_func
def original(val, r):
    res = list()
    for i in range(len(r) + 1):
        res += [list(x) for x in itertools.combinations(r, i) if sum(list(x)) == val]
    return res

@simple_time_func
def improved0(val, r):
    res = list()
    for i in range(len(r) + 1):
        res += [x for x in itertools.combinations(r, i) if sum(x) == val]
    return res


for val in range(21, 28):
    r = range(val)[1:]
    print("\nval: {}".format(val))
    for func in (original, improved0):
        res = func(val, r)
        #print("    Solution : %s " % res)
        #print("    Combinations : %s" % len(res))
注释

  • 我将昂贵的部分(循环的
    )封装在一个函数(
    original
    )中,以便计时
  • 我将改进的循环放在另一个函数中(称之为
    improved0
  • 代码的其余部分(不幸的是,也是大部分)只是用于性能测试
输出

如输出所示,这一显然微不足道的变化几乎将时间缩短了一半。

下一步包括real优化(因为计算复杂度仍呈指数级增长),即高效利用数学和编程技能,以进一步提高速度(不幸的是,我的时间不多了).

我要做的是返回每个小于n的数字组合,并且不重复。因此,对于输入6,返回值为[1,5],[1,2,3],[2,4]。我的代码返回这些很好的结果,然后说明组合的数量,在本例中为3,但当我输入大于25的值时,返回所需的时间要长得多,我知道返回是指数的,但141个组合的结果不应该花费这么长的时间。您的代码所做的是查找每个组合,包括无效的组合,然后扔掉所有东西,除了你想留下的那几个。因此,对于25的和值,即16777216个组合,您的代码将通过搜索找到有效的组合。所有这些组合随着你价值的增加而加倍。我用一个有效的解决方案编辑了我的答案,这个解决方案在这些规模下运行得快得多。我现在看到了,这要快得多。谢谢Zulfiqaar:你不应该盲目地复制代码。
with_replacement
关键字参数实际上不用于
a()
\u a()
函数中的任何内容(除了从前者传递到后者,这样它也可以忽略)。感谢您的帮助,我非常感谢。不客气,我会回到这里,因为我觉得有一种(更)快速的方法。
import time
import itertools

#val = int(input("val:"))
#r = range(val)[1:]

def simple_time_func(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        r = func(*args, **kwargs)
        print("{} took {:.3f} seconds.".format(func.__name__, time.time() - start))
        return r
    return wrapper

@simple_time_func
def original(val, r):
    res = list()
    for i in range(len(r) + 1):
        res += [list(x) for x in itertools.combinations(r, i) if sum(list(x)) == val]
    return res

@simple_time_func
def improved0(val, r):
    res = list()
    for i in range(len(r) + 1):
        res += [x for x in itertools.combinations(r, i) if sum(x) == val]
    return res


for val in range(21, 28):
    r = range(val)[1:]
    print("\nval: {}".format(val))
    for func in (original, improved0):
        res = func(val, r)
        #print("    Solution : %s " % res)
        #print("    Combinations : %s" % len(res))
(py35x64_test) c:\Work\Dev\StackOverflow\q46853086>"c:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" a.py

val: 21
original took 0.573 seconds.
improved0 took 0.325 seconds.

val: 22
original took 1.185 seconds.
improved0 took 0.633 seconds.

val: 23
original took 2.388 seconds.
improved0 took 1.300 seconds.

val: 24
original took 4.880 seconds.
improved0 took 2.609 seconds.

val: 25
original took 9.796 seconds.
improved0 took 5.243 seconds.

val: 26
original took 19.701 seconds.
improved0 took 10.489 seconds.

val: 27
original took 39.314 seconds.
improved0 took 21.559 seconds.