我需要编写一个递归函数,用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?
我似乎缺乏对递归调用如何工作的理解,有人可以向我解释这个吗?
答案 0 :(得分: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)
答案 1 :(得分:0)
这听起来像家庭作业一样危险。为什么它必须是递归的,因为这看起来很糟糕。
无论如何,递归地你正在做的是遍历列表中的每个元素,然后将其附加到长度为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,或者中间列表为空,就可以终止递归调用。你只需要返回第一个参数。
这一切都有意义吗? (如果需要的话,我可以编写代码。我认为如果你看一下所需的callstack,它应该主要放在一起。)
答案 2 :(得分:-1)
面对这样一个基本问题(一个经常用作入门级作业或在一些编程访谈中)的一个有用的技巧是看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(对于"编程语言示例Alike Cookbook"项目)......虽然它的学术成就较少,并且倾向于更实用的编程任务。