如何查找组中所有可能的子组

时间:2014-01-14 21:42:20

标签: python recursion

假设我们有1,2,3组,所以可能的子组是:

    {1,2,3}
    {1} {2,3}
    {1,2} {3}
    {1,3} {2}
    {1} {2} {3}

你明白了。

我必须使用递归来完成它。我到目前为止(不起作用),它有点不同。 我们的想法是你有一个代表立方体的整体列表(用于建造一座塔),并且你想要建造尽可能多的高塔。所以,假设你得到了清单 多维数据集[5,2,6,6,1,1,4]和您想要的高度为7,那么最佳构建版本为[5,2] [6,1] [6,1] [4]

代码:

def find_tower(blocks, height):

    def solve(groups, cur_group, index):
        if index == len(blocks):
            return groups
        if sum(cur_group) == height:
            new_group = list(groups)
            new_group.append(cur_group)
            return solve(new_group, [], index)
        elif sum(cur_group) > height:
            return solve(groups, [], index)

        r1 = solve(groups, cur_group + [blocks[index]], index+1)
        r2 = solve(groups, cur_group, index+1)
        return max(r1, r2, key=lambda x: len(x))
    return solve([], [], 0)

但我得到[5,2] [6,1]。有什么想法吗?

4 个答案:

答案 0 :(得分:1)

我不是说以下内容有效,但它可以让您了解如何以递归方式构建结果:

import itertools

def partitions(items, n):
    if n == 1:
        return [set([e]) for e in items]
    results = partitions(items, n - 1)
    for i, j in itertools.combinations(range(len(results)), 2):
        newresult = results[i] | results[j]
        if newresult not in results:
            results.append(newresult)
    return results


items = [1,2,3]
print partitions(items, len(items))
# [set([1]), set([2]), set([3]), set([1, 2]), set([1, 3]), set([2, 3]), set([1, 2, 3])]

答案 1 :(得分:1)

这是一种使用递归的简单方法。我们的想法是,对于包含x和其他一些元素xs的列表,子集集合是xs的所有子集,加上xs的子集x 1}}附加。

from copy import *

def all_subsets(xs):
  if not xs:
    return [[]]
  else:
    x = xs.pop()
    subsets = all_subsets(xs)
    subsets_copy = deepcopy(subsets) # NB you need to use a deep copy here!
    for s in subsets_copy:
      s.append(x)
    subsets.extend(subsets_copy)
    return subsets

答案 2 :(得分:1)

您的主要问题是您没有重复您未使用的值,例如: 首先你拿5,2 超过6,6,但它不好,所以你跳过而不是6,1 但是你再也不会拿到前6,然后得到另一个6,1的组合。 这就是为什么你选择一个组合后必须重复所有值。

代码(可能更好,用你逻辑):

    def find_tower(blocks, height):

def solve(groups, cur_group, index):
    if sum(cur_group) == height:
        new_group = list(groups)# if tower is on right height
        new_group.append(cur_group)# add to groups of towers
        return solve(new_group, [], 0)
    if index == len(blocks):# if index max
        return groups
    elif sum(cur_group) > height:# if its higher than height
        return groups
    elif blocks[index] is None:# if its a None index skip
        return solve(groups, cur_group, index+1)

    temp = blocks[index]
    blocks[index] = None# changing used value to none
    r1 = solve(groups, cur_group + [temp], index+1)
    blocks[index] = temp# puttin back used value
    r2 = solve(groups, cur_group, index+1)
    return max(r1, r2, key=lambda x: len(x))# return longer group
return solve([], [], 0)

答案 3 :(得分:0)

这就是我想出来的

def find_tower(blocks,height):

    groups = []
    blocks = sorted(blocks,reverse=True)

    while sum(blocks) > height:
        curgroup = []
        running_total = height
        while sum(curgroup) < height:
            possibilities = [block for block in blocks if
                             block <= running_total]
            if possibilities:
                selected_block = blocks.index(max(possibilities))
            else:
                break
            running_total -= blocks[selected_block]
            curgroup.append(blocks.pop(selected_block))
        groups.append(curgroup)
    groups = groups+[blocks]
    return groups

输出:

IN:  print(find_tower([13,12,11,10,9,8,1,1,1,1,1,1],13))


OUT: [[13], [12, 1], [11, 1, 1], [10, 1, 1, 1], [9], [8]]
编辑:D'哦!当我看到这个问题时,我没有看到通过递归完成它的要求。我讨厌递归......让我看看我是否可以让它工作,但请给我一点时间。