python itertools.permutations_如何理解Python itertools.permutations中的全排列算法?

泻药。

大略看了一眼。

第一个元素有 n 种可能,第二个元素有 n-1 种可能,以此类推。

而观察可知 cycles 就是个 (n, n-1, n-2, ..., n-r+1) 进制的变进制数,因此 cycles 就是个计数器,直接对应到 “正在枚举输出的元素是哪个”。只不过这个变进制数的倒序对应了permutation的正序。

再注意到它给出的样例顺序非常朴素,永远是下标小的元素优先枚举,不是什么精妙的枚举顺序。带着这个信息我们再看 indices,很容易明白:cycles 为 (n, n-1, n-2..) 时,indices 为 (0, 1, 2, ..., n-1);

cycles 为 (n-1, n-1, n-2, ...) 时, indices 为 (1, 0, 2, ..., n-1); // 交换了下标为 i=0 和 j=-(n-1) 的两个元素

cycles 为 (n-2, n-1, n-2, ...) 时, indices 为 (2, 0, 1, ..., n-1); // 交换了下标为 i=0 和 j=-(n-2) 的两个元素

等等

因此 indices 就是记录一下朴素枚举顺序下的“当前排列”。

最后,注意你看的这份代码并非 python 标准库代码,而是一份为了方便理解而简化的代码。因为它说了:

Roughly equivalent to

至于这么一份为了简化的代码为什么非要用倒序枚举去做一个正序的事情,然后还时不时用 -j 去从右往左找元素(但是序列长度已知,所以从左往右找元素并不麻烦……),我觉得挺奇怪的。

EDIT: 再解释一句吧,那个代码可以看成下列递归程序的强行非递归版(省去了一些 boilerplate),注意我的版本里几乎每句话都来自原始代码,只是拆成了递归。

(cycles 哪里去了?cycles 就是栈上所有的 j)

def _perm(indices, i, n, r):

if i == r:

yield indices[:r]

else:

for j in range(n-i, 0, -1):

indices[i], indices[-j] = indices[-j], indices[i]

for result in _perm(indices, i+1, n, r):

yield result

indices[i:] = indices[i+1:] + indices[i:i+1]

def permutations(n, r):

indices = list(range(n))

return _perm(indices, 0, n, r)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值