【发布时间】:2010-12-28 07:22:39
【问题描述】:
我有一个数字列表(例如:[-1, 1, -4, 5]),我必须在不更改列表总和的情况下从列表中删除数字。我想删除绝对值最大的数字,而不改变总数,在示例中删除[-1, -4, 5] 将留下[1],因此总和不会改变。
我编写了一种简单的方法,即找出所有不改变总数的可能组合,然后看看哪个组合消除了最大的绝对值。但这真的很慢,因为实际列表会比这大得多。
这是我的组合代码:
from itertools import chain, combinations
def remove(items):
all_comb = chain.from_iterable(combinations(items, n+1)
for n in xrange(len(items)))
biggest = None
biggest_sum = 0
for comb in all_comb:
if sum(comb) != 0:
continue # this comb would change total, skip
abs_sum = sum(abs(item) for item in comb)
if abs_sum > biggest_sum:
biggest = comb
biggest_sum = abs_sum
return biggest
print remove([-1, 1, -4, 5])
它正确打印(-1, -4, 5)。但是,我正在寻找一些比遍历所有可能的项目组合更聪明、更有效的解决方案。
有什么想法吗?
【问题讨论】:
-
在这种情况下,如果我们观察到总和是这个列表中的一个项目,那就是胜利了。如果我们有
sum(items)和abs_sum(items),那么尝试使用列表中的 1、2、3 等元素加起来可能会更有效,即从空列表案例而不是完整列表开始( ?) -
您应该保存
smallest_abs_sum而不是biggest_sum。考虑:[1,-1,100,-100]. -
@J.F. Sebastian:如果输入是
[1,-1,100,-100],它应该删除所有内容(202的abs_sum)保持总和0。 -
@nosklo:我明白了:您的
remove()函数返回要删除的项目,而不是最终结果列表。
标签: python math sum combinations mathematical-optimization