【问题标题】:Combinations Recursive Algorithm组合递归算法
【发布时间】:2014-08-29 21:21:38
【问题描述】:

我需要编写一个递归函数,在 Python 中计算列表中长度“n”的所有可能组合,而无需导入 itertools 等任何内容。

所以我到目前为止是:

if n == 0:
    return [[]]
elif lst == []:
    return []
else:
    rest = subsets(lst[1:], n-1)
    for next in lst:  # Loop through something?
        return lst[0] + rest #Add something?

我似乎对递归调用的工作原理缺乏了解,有人可以向我解释一下吗?

【问题讨论】:

  • 您能帮我们解决一下缩进问题吗?点击帖子下方的“编辑”按钮。
  • 抱歉,现在应该更清楚了
  • 你的函数叫subsets吗?如果是这样,您可以在其中包含函数标题吗?
  • 一个我问过自己很多次的问题。也许开始获取列表长度以下的“n”个数字的所有组合(包括零),然后按索引获取元素。
  • 另外:如果您只想要独特的输出,了解组合的顺序是否重要很重要。 [a, b] 和 [b, a] 都算吗?还是只是[a,b]?假设列表是 [a, b, c] 并且您想要 2-len 子集。 [a, a] 是有效的输出吗?

标签: python recursion combinations


【解决方案1】:

在没有所需的输出规范的情况下,我们可以编写一些伪代码,如下所示:

def combinations(sub, data_set, items_needed):
    if you dont need, return sub
    for item in data_set:
        append item to sub
        #pop() item from data_set?
        decrease items_needed # added one more, so we need one less
        combinations(new_sub, data_set, items_needed)

poping() 与否取决于您想要(或不想要)子集中的唯一项目。

如果您说不想同时使用 [a, b] 和 [b, a],您还必须跟踪添加的最后一个项目的索引,以便仅添加新项目以创建新组合.

def combinations(sub, data_set, index, still_needed):
    if you dont need any, return
    for i in range(index, len(data_set)):
        append data_set[i] to sub
        decrease still_needed
        combinations(sub, data_set, index+1, still_needed)

【讨论】:

  • 谢谢,很抱歉没有提供规范我只需要解释算法的工作原理,这就解决了!
  • @BurhanKhalid 将变量名称更改为 data_set。感谢您的提醒
【解决方案2】:

这听起来很危险,就像一个家庭作业问题。为什么它必须是递归的,因为这看起来很糟糕。

无论如何,递归地你正在做的是遍历列表中的每个元素,然后将其附加到长度为 n - 1 的所有其他组合的开头。所以,如果你的列表是 [1, 2, 3],你想要一个调用堆栈看起来像这样的算法:

foo([], [1, 2, 3], n) ==
  foo([1], [2, 3], n - 1) +
  foo([2], [1, 3], n - 1) +
  foo([3], [1, 2], n - 1)

在哪里,

foo([1], [2, 3], n - 1) ==
  foo([1, 2], [3], n - 2) +
  foo([1, 3], [2], n - 2)

等等……

只要 n == 0 或中间列表为空,您就可以终止递归调用。你只需返回第一个参数。

这一切都有意义吗? (如果需要,我可以对其进行编码。我认为如果您查看所需的调用堆栈,它应该主要将自己放在一起。)

【讨论】:

  • 您可能不需要n,因为它可以根据其中一个列表的长度来计算。
  • 请记住,由于 foo() 函数是递归调用的,因此您始终使用 n - 1 进行内部调用
  • @ssm 拥有一个保存该值的变量可能比无限次调用len(subset) 更好。
  • 是的,把它写成 n - 2 是相当具有误导性的。如果 (n - 1) - 1 看起来会更好吗?
【解决方案3】:

面对这样一个基本问题(经常用作入门级作业或在某些编程面试中使用的问题)时,一个有用的技巧是查看RosetteCode(您也可以从中学习如何打动您的朋友像“chrestomathy”这样的词)。对于这一点,我们特别发现:

#/usr/bin/env python
# From: http://rosettacode.org/wiki/Combinations#Python
def comb(m, lst):
if m == 0:
    return [[]]
else:
    return [[x] + suffix for i, x in enumerate(lst)
            for suffix in comb(m - 1, lst[i + 1:])]

...与几十种其他语言的实现一起进行比较。

另一个方便的站点是PLEAC(用于“Programming Language Examples Alike Cookbook”项目)......虽然它的学术性较低,并且倾向于更实用的编程任务。

【讨论】:

  • -1 这是一个基本问题,因为他正在学习,立即得到答案并不能帮助他实现真正的目标
猜你喜欢
  • 2012-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多