繁体   English   中英

使用递归计算长度为n的列表中的长度k的组合

[英]Calculating combinations of length k from a list of length n using recursion

我需要从长度为n的列表生成长度为k所有组合,我必须使用递归来完成。

例如:

INPUT:  choose_sets([1,2,3,4],3)
OUTPUT: [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
INPUT:  choose_sets([1,2,3,4],2)
OUTPUT: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]

我在代码中执行此操作时遇到困难,所以我很乐意提供一些帮助。 到目前为止这是我的代码(我遗漏的东西只是不知道是什么):

def choose_sets(lst,k):

    if k == len(lst):
        return lst
    if k == 0:
        return []
    if k > len(lst):
        return []

    sets=[]
    sub_lst=lst[:]
    sub_lst.remove(sub_lst[0])

    a= choose_sets(sub_lst,k-1)
    for i in a:
        i.append(lst[0])
    sets.append(a)

    b= choose_sets(sub_lst,k)
    sets.append(b)


    return sets

您可以从Generator获取解决方案的排列,组合和选择(Python配方)

def xuniqueCombinations(items, n):
    if n==0: yield []
    else:
        for i in xrange(len(items)):
            for cc in xuniqueCombinations(items[i+1:],n-1):
                yield [items[i]]+cc



>>> def xuniqueCombinations(items, n):
...     if n==0: yield []
...     else:
...         for i in xrange(len(items)):
...             for cc in xuniqueCombinations(items[i+1:],n-1):
...                 yield [items[i]]+cc
... 
>>> for x in xuniqueCombinations( [1,2,3,4],2):
...     print x
[1, 2]
[1, 3]
[1, 4]
[2, 3]
[2, 4]
[3, 4]

4年后编辑 (2015 年12月 7日)

要在Python3上运行它只需将xrange更改为rangePython3的范围是Python2的xrange。 谢谢@ederollora注意到我。

这是Java,我不能保证它100%正常工作,但基于快速原型设计似乎工作正常。 希望这在任何情况下都有所帮助。

public void choose_sets(int values[], int count) {
    int perm[] = new int[count];
    choose_sets(values, 0, perm, 0, count);
}

public void choose_sets(int[] values, int valuesIdx, int[] perm,
                        int permIdx, int count) {
    if (permIdx == count) {
        // At this point perm -array contains single permutation
        // of length ´count´.
    } else {
        for (int i = valuesIdx; i < values.length; ++i) {
            perm[permIdx] = values[i];
            choose_sets(values, i + 1, perm, permIdx + 1, count);
        }
    }
}

看看这个解决方案:

def choose_sets(mylist,length):
    mylen = len(mylist)

    if length == mylen:
        return [mylist]
    if length == 1:
        return [[i] for i in mylist]
    if length > mylen:
        return []

    ToRet = []
    for k in xrange(mylen): 
        if mylen - k + 1> length :
            for j in choose_sets(mylist[k+1:],length-1):
                New = [mylist[k]]
                New.extend(j)
                ToRet.append(New)
    return ToRet

print choose_sets([1,2,3,4,5],3)

有更优雅的方式,但这应该是作为功课...

你几乎就在那里,只是一些小事。 该算法基本上是正确的,但是

if k == len(lst):
    return lst

这有错误的类型。 返回类型不是事物的列表,而是( 事物列表)的列表,所以应该是

if k == len(lst):
    return [lst]

下一个,

if k == 0:
    return []

每个列表都有一个非空的子列表,空列表,所以应该是

if k == 0:
    return [[]]

对于其余的,

if k > len(lst):
    return []

是完全正确的。

sets=[]
sub_lst=lst[:]
sub_lst.remove(sub_lst[0])

这是正确的,但可以更简洁地说

sub_lst = lst[1:]

现在,另一种类型的混淆:

a= choose_sets(sub_lst,k-1)
for i in a:
    i.append(lst[0])
sets.append(a)

sets.append(a)a成一个槽sets ,要连接两个列表, sets = sets + a 如果你想按照元素出现在列表中的顺序组合,而不是i.append(lst[0]) ,你应该将[lst[0]] + i追加到循环中的sets ,但那是一个倾向的问题。

b= choose_sets(sub_lst,k)
sets.append(b)

再次,不要追加,但在这里连接,

sets = sets + b

基本上你需要使用以下递归:

f(k,n)= append_to_each(f(k-1,n-1),n)| F(K,N-1)

def combinations(lst,k):
    n = len(lst)
    if n == k:
        return [set(lst)]
    if k == 1:
        return [set([lst[i]]) for i in range(n)]
    v1 = combinations(lst[:-1], k-1)
    v1new = [ i.add(lst[n-1]) for i in v1]
    v2 = combinations(lst[:-1], k)
    return v1+v2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM