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

发布于 2024-12-23 07:23:08 字数 726 浏览 2 评论 0原文

我需要从长度为 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

I need to generate all the combinations with length k from a list of length n, and I must do it using recursion.

For Example:

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]]

I'm stuck implementing this in code, so I would be happy for some help.
This is my code so far (I'm missing something just don't know what):

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

把昨日还给我 2024-12-30 07:23:08

您可以从 排列、组合、选择的生成器获得解决方案一个序列(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 年 7 月 12 日)

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

You can get solution from Generator for permutations, combinations, selections of a sequence (Python recipe)

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]

Edited 4 year later (7/12/2015)

To run it on Python3 just change xrange to range, Python3's range is Python2's xrange.. Thanks @ederollora to notice me.

从﹋此江山别 2024-12-30 07:23:08

看看这个解决方案:

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)

还有更优雅的方法,但这应该可以作为家庭作业......

Give a look to this solution:

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)

there are more elegant ways, but this should be ok as homework...

清君侧 2024-12-30 07:23:08

这是用 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);
        }
    }
}

This is in Java, and I can't guarantee it works 100% properly, but based on quick prototyping seemed to work ok. Hope this helps a bit in any case.

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);
        }
    }
}
疾风者 2024-12-30 07:23:08

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

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

basically you need to use the following recursion:

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
零崎曲识 2024-12-30 07:23:08

你已经快到了,只需要一些小事情。该算法基本上是正确的,但是

if k == len(lst):
    return lst

This 的类型错误。返回类型不是 thing 列表,而是 (thing 列表) 列表,因此应该是

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

Next,

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< 的一个槽中/code>,您想要连接两个列表,sets = sets + a。如果您希望按照元素在列表中出现的顺序进行组合,则应附加 [lst[0]] +,而不是 i.append(lst[0]) i 到循环中的sets,但这是一个倾向问题。

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

再次强调,不要追加,而是在这里连接,

sets = sets + b

You are almost there, just a few minor things. The algorithm is basically correct, but

if k == len(lst):
    return lst

This has the wrong type. The return type is not a list of thing, but a list of (list of thing), so that should be

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

Next,

if k == 0:
    return []

Every list has exactly one nonempty sublist, the empty list, so that ought to be

if k == 0:
    return [[]]

For the rest,

if k > len(lst):
    return []

is completely correct.

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

That is correct but could be put more succinctly as

sub_lst = lst[1:]

Now, another type mix-up:

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

That sets.append(a) puts a into one slot of sets, you want to concatenate the two lists, sets = sets + a. And if you would like the combinations in the order in which elements appear in the list, instead of i.append(lst[0]), you should append [lst[0]] + i to sets in the loop, but that's a matter of inclination.

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

Again, do not append, but concatenate here,

sets = sets + b
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文