python用函数创建列表_如何使用递归函数创建包含n个元素的列表置换列表?|Python...

您可以这样递归地解决问题:def perm(n, a):

# recursion anchor

if n <= 0:

return [[]]

else:

result = []

for smallPerm in perm(n-1, a):

# take all elements from a

for elem in a:

# and prepend them to all permutations we get from perm(n-1, 1)

result.append([elem] + smallPerm)

return result

您可以将函数编写为两行代码,但我决定将其编写得更详细一些,以便更易于理解。

不知道你对递归有多少了解,但我知道对于初学者来说这并不容易理解。。。让我来解释一下。

在每个递归函数中,都需要一个递归锚点。这是函数不递归而是直接传递结果的点。它通常是定义良好的基本/原子情况。在本例中,n==0。由于只存在一个包含0个元素的置换,即空列表,因此返回一个包含空列表的列表。

我把n<=0放在那里,这样如果一些smartcookie用n=-1调用perm,我们就不会遇到麻烦,但是n<0的例外情况也能解决这个问题。

现在你在这个锚定的基础上,说,好吧,我的函数给出了n==0的正确结果,所以当我的当前n为1时,我可以信任它,我用n-1调用它。现在的诀窍是相信它会为每一个n-1得到正确的结果,不管你从哪里开始!你可能想知道这是怎么可能的。递归函数就是这样,当你编写递归函数时,你已经依赖它们做正确的工作了。

现在这意味着调用perm(n-1, a)会给你所有长度为n-1的排列。接下来要做的就是用a中的所有元素附加(或预先添加)这些排列,这样就有了一个大小为n的排列列表!工作完成了。

但是请注意,有时需要有多个锚定或一个处理多个输入可能性的锚定。

例如著名的低效fibonacci函数:

^{pr2}$

需要两个锚点,因为使用fib(n - 2)可以后退两步!

随访:

为什么这个功能效率低下?原因与Stefan在评论我的第一个解决方案时所指出的相似。

我犯了一个错误,把递归调用放在一个循环中。这不一定是错误的,但在本例中,调用的参数没有被外部循环更改,这使得它不必要。因此,它每次都会重新生成相同的列表,而不是只生成一次然后再保留它。最糟糕的是所有的递归实例都是一样的!

通过观察分支因子,可以看出这有多糟糕。这里的fib函数调用自己两次,这意味着它的分支因子是2。因此,如果您的解决方案需要深入n个步骤,那么您将对该函数进行2^n个计算。

虽然这个分支因子是常量,但我的第一个实现为a中的每个元素调用了自己,因此分支因子等于列表中元素的数量。

我很高兴Stefan没有尝试过perm(20,[1,2,3])这将是3^20的评价,大约是他所尝试的2^20次评价的3000倍。是的,增加了三千倍只是因为多一个元素。这是指数运行时间!

为了简单起见,我忽略了这样一个事实,即问题本身已经按len(a)**n扩展。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值