【发布时间】:2017-11-18 06:04:51
【问题描述】:
我是 Python 新手,我正在通过 Codewars 慢慢学习。我知道这可能违反规则,但我有一个效率问题。
给你一个整数列表
ls = [100, 76, 56, 44, 89, 73, 68, 56, 64, 123, 2333, 144, 50, 132, 123, 34, 89]
你必须写一个函数choose_best_sum(t, k, ls)
这样你就可以从 ls 中找到 k 个整数的组合,使得这些 k 个整数的总和接近或等于 t。
我的最终解决方案通过了测试,但在更详细的测试中失败可能是因为效率。我试图更多地了解效率。这是我的代码
import itertools
def choose_best_sum(t, k, ls):
if sum(sorted(ls)[:k]) > t or len(ls) < k:
return None
else:
combos = itertools.permutations(ls, k)
return max([[sum(i)] for i in set(combos) if sum(i) <= t])[0]
有人可以强调瓶颈在哪里(我假设在 permutations 调用中)以及如何使这个函数更快?
编辑:
上面介绍的解决方案给出了
0.458 秒内调用 1806730 个函数
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.457 0.457 <string>:1(<module>)
1 0.000 0.000 0.457 0.457 exercises.py:14(choose_best_sum)
742561 0.174 0.000 0.305 0.000 exercises.py:19(<genexpr>)
321601 0.121 0.000 0.425 0.000 exercises.py:20(<genexpr>)
1 0.000 0.000 0.458 0.458 {built-in method builtins.exec}
1 0.000 0.000 0.000 0.000 {built-in method builtins.len}
1 0.032 0.032 0.457 0.457 {built-in method builtins.max}
1 0.000 0.000 0.000 0.000 {built-in method builtins.sorted}
742561 0.131 0.000 0.131 0.000 {built-in method builtins.sum}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
使用帮助我得到的最终解决方案是:
def choose_best_sum(t, k, ls):
ls = [i for i in ls if i < t and i < (t - sum(sorted(ls)[:k-1]))]
if sum(sorted(ls)[:k]) > t or len(ls) < k:
return None
else:
return max(s for s in (sum(i) for i in itertools.combinations(ls, k)) if s <= t)
排序者:标准名称
7090 次函数调用在 0.002 秒内
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.003 0.003 <string>:1(<module>)
2681 0.001 0.000 0.003 0.000 exercises.py:10(<genexpr>)
1 0.000 0.000 0.003 0.003 exercises.py:5(choose_best_sum)
1 0.000 0.000 0.000 0.000 exercises.py:6(<listcomp>)
1 0.000 0.000 0.003 0.003 {built-in method builtins.exec}
1 0.000 0.000 0.000 0.000 {built-in method builtins.len}
1 0.000 0.000 0.003 0.003 {built-in method builtins.max}
17 0.000 0.000 0.000 0.000 {built-in method builtins.sorted}
4385 0.001 0.000 0.001 0.000 {built-in method builtins.sum}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
【问题讨论】:
-
查看
cProfile以确定哪条线路慢。 -
瓶颈是你正在使用的算法,当你有一个大列表时,列出所有的排列很慢。尝试在排序列表上使用两个指针(一个在开头,一个在结尾),其时间复杂度为 O(nlogn)
-
@GhostRider 是的,这是代码战...除了我链接到 正在讨论的实际问题,而不是在现场挥手。
标签: python algorithm performance processing-efficiency