我接受Gareth Rees的回答是最吸引人的解释(缺少Python库设计者的回答),也就是说,Python的next_permutation不会比较元素的值。 想一想,这就是问题的所在,但是我现在看到如何将其视为优势,这取决于人们通常使用next_permutation的用途。
为了完整起见,我比较了生成所有不同排列的三种方法。 方法1在内存和时间上效率都很低,但需要最少的新代码,方法是包装Python的next_permutation,如zeekay的回答。 方法2是此博客文章中C ++ next_permutation的基于生成器的版本。 我写的方法3更接近C ++的next_permutation算法; 它就地修改了列表(我没有做得太笼统)。
def next_permutationS(l):
n = len(l)
#Step 1: Find tail
last = n-1 #tail is from `last` to end
while last>0:
if l[last-1] < l[last]: break
last -= 1
#Step 2: Increase the number just before tail
if last>0:
small = l[last-1]
big = n-1
while l[big] <= small: big -= 1
l[last-1], l[big] = l[big], small
#Step 3: Reverse tail
i = last
j = n-1
while i < j:
l[i], l[j] = l[j], l[i]
i += 1
j -= 1
return last>0
这是一些结果。 我现在更加尊重Python的内置函数:当元素全部(或几乎全部)不同时,它的速度是其他方法的三到四倍。 当然,当有很多重复的元素时,使用它是一个糟糕的主意。
Some results ("us" means microseconds):
l m_itertoolsp m_nextperm_b m_nextperm_s
[1, 1, 2] 5.98 us 12.3 us 7.54 us
[1, 2, 3, 4, 5, 6] 0.63 ms 2.69 ms 1.77 ms
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 6.93 s 13.68 s 8.75 s
[1, 2, 3, 4, 6, 6, 6] 3.12 ms 3.34 ms 2.19 ms
[1, 2, 2, 2, 2, 3, 3, 3, 3, 3] 2400 ms 5.87 ms 3.63 ms
[1, 1, 1, 1, 1, 1, 1, 1, 1, 2] 2320000 us 89.9 us 51.5 us
[1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4] 429000 ms 361 ms 228 ms
如果有人想探索,请在这里找到代码。