给定一个数字列表,如何创建总和的所有组合并返回这些总和的列表

Posted

技术标签:

【中文标题】给定一个数字列表,如何创建总和的所有组合并返回这些总和的列表【英文标题】:Given a list of numbers, how do you create all the combinations of sums and return a list of those sum 【发布时间】:2021-05-28 23:52:33 【问题描述】:

假设我们有一个数字列表 [1,2,3],我们必须将所有可能的元素总和组合附加到一个数组中并返回该数组?

如何获得以下总和

1 = 1 (the first element so simply add it to the ans array)
1 + 2 = 3
1 + 3 = 4
1 + 2 + 3 = 6
1 + 3 + 2 = 6
2 = 2 (second element so simply add it to ans array)
2 + 1 = 3
2 + 3 = 5
2 + 1 + 3 = 6
2 + 3 + 1 = 6
3 + 1 = 4
3 = 3 (third element so simply add it to ans array)
3 + 1 = 4
3 + 2 = 5
3 + 1 + 2 = 6
3 + 2 + 1 = 6

所以我们的最终数组看起来像 [1,3,4,6,6,2,3,5,6,6,3,4,5,6,6]

【问题讨论】:

为什么1 + 2 + 3 = 61 + 3 + 2 = 6的名字编号顺序不同,而1 + 3 = 43 + 1 = 4却不包括在内? 订单重要吗? 是的,订单应该很重要。这样它也可以应用于字符串。 我尝试了回溯,但无法解决如何解决问题?它看起来类似于生成元素列表的所有子序列。 【参考方案1】:

使用itertools.permutations

>>> import itertools
>>> nums = [1, 2, 3]
>>> [sum(p) for n in range(1, len(nums)+1) for p in itertools.permutations(nums, n)]
[1, 2, 3, 3, 4, 3, 5, 4, 5, 6, 6, 6, 6, 6, 6]

如果您想确切了解 permutations 正在做什么,而不仅仅是查看最终结果,您可以使用 mapjoin 做一些有趣的事情:

>>> [f"'+'.join(map(str, p))=sum(p)" for n in range(1, len(nums)+1) for p in itertools.permutations(nums, n)]
['1=1', '2=2', '3=3', '1+2=3', '1+3=4', '2+1=3', '2+3=5', '3+1=4', '3+2=5', '1+2+3=6', '1+3+2=6', '2+1+3=6', '2+3+1=6', '3+1+2=6', '3+2+1=6']

【讨论】:

【参考方案2】:

使用itertools

import itertools

nums = [1,2,3]
results = []

def split(a, n):
    k, m = divmod(len(a), n)
    return [a[i*k+min(i, m):(i+1)*k+min(i+1, m)] for i in range(n)]
        
for i in range(len(nums)):
    results.append(split(list(map(sum,itertools.permutations(nums,i+1))),len(nums)))

results = zip(*results)
results = list(itertools.chain.from_iterable(itertools.chain.from_iterable(results)))

print(results)
>>> [1, 3, 4, 6, 6, 2, 3, 5, 6, 6, 3, 4, 5, 6, 6]

【讨论】:

【参考方案3】:

这是递归问题的一个很好的例子。

要解决这个问题,您需要一个调用自身并在给定条件处停止的函数。

const getResults = (numbers, usedNumbers, results) => 
  if (usedNumbers.length >= numbers.length) return;

  numbers.forEach(number => 
    if (usedNumbers.includes(number)) return;

    const result = usedNumbers.reduce((acc, curr) => acc + curr, number);
    console.log(`$[...usedNumbers, number].join(' + ') = $result`)
    results.push(result);
  );

  numbers.forEach(number => 
    if (! usedNumbers.includes(number)) getResults(numbers, [...usedNumbers, number], results);
  )
;

const numbers = [1,2,3];
const results = [];
numbers.forEach(number => 
  results.push(number);
  console.log(`$number = $number`)
  getResults(numbers, [number], results);
);

console.log(results);

【讨论】:

以上是关于给定一个数字列表,如何创建总和的所有组合并返回这些总和的列表的主要内容,如果未能解决你的问题,请参考以下文章

给定一个数字列表,找到所有矩阵,使得每列和每行总和为 264

获取加起来等于给定数字的所有可能总和

回溯 - 给定一组数字,找到总和等于 M 的所有子集(给定 M)

如何使用 chez 方案获得给定列表中所有元素的总和 >10?

如何返回所有具有 N 总和的唯一数字组合 [重复]

求和一系列数字