如何从元组创建所有组合的总和? (采访)

时间:2018-03-11 19:19:31

标签: python tuples combinations

我在面试时遇到一个问题,这很有挑战性。该主题基于决策分析。问题是让我们假设我们有一个元组;

(15, 8, 8, 3)

我们希望逐个创建所有组合的所有总和,而不重复和求和相同的数字,例如此输出;

[(23, 8, 3), (18, 8, 8), (15, 11, 8)]

另一个例子;

(6, 5, 3, 8)

输出是:

[(11, 3, 8), (9, 5, 8), (14, 5, 3), (6, 8, 8), (6, 13, 3), (6, 5, 11)]

注意:订单很灵活。

我真的很想知道答案,所以如果有人对这个编码挑战感兴趣,会帮助我改善思维结构。

3 个答案:

答案 0 :(得分:5)

我认为解决此类问题的最佳方法是从缓慢,强力的解决方案开始,因为这样您就可以直观地看到工作的进展情况。其他人不同意并且更愿意预先考虑可能的算法,但这是我的答案,所以......

首先忽略重复的数字规则,使事情更简单:

def sumcombos(tup):
    for i, x in enumerate(tup):
        for j, y in enumerate(tup[i+1:], i+1):
            yield tup[:i] + (x+y,) + tup[i+1:j] + tup[j+1:]

你应该能够理解它是如何工作的,对吧?

如果您明确需要list tuple而不是任何可迭代的,请将其换行:

def sumcomboslist(lst):
    return list(sumcombos(lst))

现在,问题是这将输出(23, 8, 3)两次,并且它还将输出(15, 16, 3)。避免这种情况的规则是"不重复和总结相同的数字"。解释这意味着什么并不容易, * 但是一旦你这样做,实现它是:

def sumcombos(lst):
    for i, x in enumerate(lst):
        if x in lst[:i]: continue
        for j, y in enumerate(lst[i+1:], i+1):
            if y in lst[:j]: continue
            yield tup[:i] + (x+y,) + tup[i+1:j] + tup[j+1:]

那么,表现是什么?好吧,内循环显然会运行N**2次,并且我们有一个if y in lst[:j]在该循环中占用线性时间,所以它是N**3。现在,对于我们的例子,有史以来最大的N是4,这很好,但在大多数现实情况下,立方算法都是个问题。

如果我们可以使用线性空间,我们可以通过构建一个前端将每个值映射到其第一个位置(仅需要线性时间)来改进它,然后if y in lst[:j]:成为常量时间{ {1}}。

然后我们可以将这个memoization更进一步并缓存所有子列表的结果,因此内部循环只需要在第一次计算每个子目录。

但是,一旦你完成了这项工作,你就可以看到实际发生了什么(如果没有,在中间添加一些if first_positions[y] < j:)并提出更聪明的算法来存储所有内容预先结对。

*规则很模糊,本页面上的每个人(包括我)都错误地认为它是什么意思。考虑到可以解释和查看预期输出的所有方式,我想我可以弄清楚它们必须具有什么意义。但在现实生活中,我绝对会要求他们澄清而不是猜测。对于一次采访来说更是如此,让你要求澄清可能实际上就是重点。

答案 1 :(得分:1)

set

答案 2 :(得分:0)

您可以尝试这种方法:

import itertools

final_=[]
for m in list(itertools.permutations(order,r=4)):
    if m[:2][0]==m[:2][1]:
        pass
    else:
        final_.append(tuple(sorted((sum(m[:2]),)+m[2:])))

print(set(final_))

输出:

when order=(15, 8, 8, 3)

输出:

{(3, 8, 23), (8, 8, 18), (8, 11, 15)}

order=(6, 5, 3, 8)

输出:

{(5, 8, 9), (3, 8, 11), (3, 5, 14), (6, 8, 8), (5, 6, 11), (3, 6, 13)}