【问题标题】:Find K subsets of a list with elements 1...N while preserving the order of the elements查找具有元素 1...N 的列表的 K 个子集,同时保留元素的顺序
【发布时间】:2019-08-16 07:26:16
【问题描述】:

给定一个来自 1...N 的整数列表,我试图找到元素的 K 个子集,同时保留元素的顺序。例如,当 N = 4 且 K = 2 时:

[1] [2, 3, 4]

[1, 2] [3, 4]

[1, 2, 3] [4]

[1, 2, 3, 4] []

应该是正确的输出。 到目前为止,我已经得到了第一列可能性。但我很难得到正确的逻辑。

    final = [['' for x in range(K)] for y in range(N)]
    i = 0
    for k in range(0, K):
        # row tracker
        i = 0
        while i < N:
            if k > 0:
                st = len(final[i][k - 1])
            else:
                st = 0
            for j in range(0, N):
                tmp = ""
                prefix = chemicals[:j + 1]
                tmp = tmp.join(str(i) for i in prefix)
                final[i][k] = tmp
                i += 1
        print

同样,正确的输出应该是:

[1] [2, 3, 4]

[1, 2] [3, 4]

[1, 2, 3] [4]

[1, 2, 3, 4] []

集合可以是空的。

更新:这是 N=4、K=3 的正确输出

[1] [2] [3, 4]
[1] [2, 3] [4]
[1] [2, 3, 4] []
[1, 2] [3] [4]
[1, 2] [3, 4] []
[1, 2, 3] [4] []
[1, 2, 3, 4] [] []

【问题讨论】:

  • [1,2,3,4] [] [] 会成为 N=4、K=3 解决方案的一部分吗?
  • 是的,那是正确的

标签: python dynamic-programming combinatorics


【解决方案1】:

我认为一个简单的带有切片的列表理解就足够了。您可能还想使用itertools.combinations:

import itertools

N = 4
K = 2

elements = list(range(1, N + 1))
final = [[elements[a:b] for a, b in zip([0] + cuts, cuts + [N])]
                        for cuts in (list(c) for c in itertools.combinations(elements, K - 1))]

for x in final:
    print(*x)

输出:

[1] [2, 3, 4]
[1, 2] [3, 4]
[1, 2, 3] [4]
[1, 2, 3, 4] []

【讨论】:

  • 嗨,我更新了我的输出。当 N=4, K=3 时,应该有另一行带有两个空集的输出
【解决方案2】:

您可以使用从给定起始编号迭代索引的函数,默认为1,到n,产生从起始编号到索引的数字范围,并递归连接来自递归的子集使用一个高一个子集和一个小一个子集的起始索引进行调用,直到起始索引大于n 或k 变为1,此时应产生剩余范围:

def get_subsets(n, k, s=1):
    if s > n or k == 1:
        yield [list(range(s, n + 1))] + [[] for _ in range(1, k)]
        return
    for i in range(s, n + 1):
        for subsets in get_subsets(n, k - 1, i + 1):
            yield [list(range(s, i + 1))] + subsets

这样:

for s in get_subsets(4, 2):
    print(*s)

输出:

[1] [2, 3, 4]
[1, 2] [3, 4]
[1, 2, 3] [4]
[1, 2, 3, 4] []

还有:

for s in get_subsets(4, 3):
    print(*s)

输出:

[1] [2] [3, 4]
[1] [2, 3] [4]
[1] [2, 3, 4] []
[1, 2] [3] [4]
[1, 2] [3, 4] []
[1, 2, 3] [4] []
[1, 2, 3, 4] [] []

【讨论】:

  • 您好,感谢您的帮助。我认为 n=4 和 k=3 不会产生正确的输出。应该有 3 个集合中有 2 个为空的情况: [1, 2, 3, 4] [] [] 附带问题:有没有办法在没有生成器的情况下做到这一点?像纯粹的递归或迭代方式?
  • 很高兴能提供帮助。你能用你对 n=4 和 k=3 的预期输出来更新你的问题吗?
  • 抱歉不小心过早提交了评论(试图编辑)。输出将是:[1] [2] [3, 4]... [1] [2, 3] [4]... [1] [2, 3, 4] []... [1, 2] [3] [4]... [1, 2] [3, 4] []... [1, 2, 3] [4] []... [1, 2, 3, 4] [] []...
  • 啊,我明白了。那就修好了。
猜你喜欢
  • 1970-01-01
  • 2018-12-08
  • 1970-01-01
  • 2019-08-20
  • 2012-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-03
相关资源
最近更新 更多