查找元素为1 ... N的列表的K个子集,同时保留元素的顺序

时间:2019-03-26 00:26:29

标签: python dynamic-programming combinatorics

给出一个从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] [] []

2 个答案:

答案 0 :(得分:0)

我认为对切片的简单列表理解就足够了。您可能还需要使用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] []

答案 1 :(得分:0)

您可以使用一个函数,该函数从给定的起始编号(默认为1n迭代索引,产生从起始编号到索引的一系列数字,然后递归连接递归调用的子集,其起始索引要高一个,子集要少一个,直到起始索引大于nk变为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] [] []