繁体   English   中英

Python itertools 排列不重复

[英]Python itertools permutations without repetitions

我有一个字符串显示 mxn 网格中的步骤,就像这个问题: https : //leetcode.com/problems/unique-paths/

step = 'DDRR'

D 表示向下,R 表示向右,我想显示不替换的排列,我发现 Python 内置了 itertools。但它说:

元素被视为唯一基于它们的位置,而不是它们的值。 所以如果输入元素是唯一的,就不会有重复值。

所以当我使用 itertools.permutation(step,4) 时,它包含许多复制。

>>> itertools.permutations(step,4)
('D', 'D', 'R', 'R')
('D', 'R', 'D', 'R')
('D', 'R', 'R', 'D')
('D', 'R', 'D', 'R')
('D', 'R', 'R', 'D')
('D', 'D', 'R', 'R')
('D', 'D', 'R', 'R')
('D', 'R', 'D', 'R')
('D', 'R', 'R', 'D')
('D', 'R', 'D', 'R')
('D', 'R', 'R', 'D')
('R', 'D', 'D', 'R')
('R', 'D', 'R', 'D')
('R', 'D', 'D', 'R')
('R', 'D', 'R', 'D')
('R', 'R', 'D', 'D')
('R', 'R', 'D', 'D')
('R', 'D', 'D', 'R')
('R', 'D', 'R', 'D')
('R', 'D', 'D', 'R')
('R', 'D', 'R', 'D')
('R', 'R', 'D', 'D')
('R', 'R', 'D', 'D')

我想要这样的东西:

('R', 'D', 'R', 'D')
('R', 'D', 'D', 'R')
('D', 'R', 'R', 'D')
('D', 'D', 'R', 'R')
('D', 'R', 'D', 'R')
('R', 'R', 'D', 'D')

我使用set(itertools.permutations(step,4))找到了一些答案,但是因为应用 set() 方法, itertools.permutation() 方法仍然计算所有可能性。 无论如何要避免它,或者是否有任何内置函数可以在 Python 中不重复地进行排列

要获得您需要的答案,您可以使用multiset_permutations

>>> from sympy.utilities.iterables import multiset_permutations
>>> from pprint import pprint
>>> pprint(list(multiset_permutations(['D','D','R','R'])))
[['D', 'D', 'R', 'R'],
 ['D', 'R', 'D', 'R'],
 ['D', 'R', 'R', 'D'],
 ['R', 'D', 'D', 'R'],
 ['R', 'D', 'R', 'D'],
 ['R', 'R', 'D', 'D']]

要获得总数,请使用项目数的阶乘除以阶乘的乘积来计算每个唯一项目的数量。 这里有2个D和2个R

>>> from math import factorial
>>> factorial(4)//(factorial(2)*factorial(2))
6

leetcode 问题只询问唯一路径的数量,而不是唯一路径的列表,因此计算数量只需要使用C(n, k) = n! / (k! x (n - k)!)的组合公式即可C(n, k) = n! / (k! x (n - k)!) C(n, k) = n! / (k! x (n - k)!)找出所有位置中可以放置D s(或R s)的位置数:

from math import factorial

def f(m, n):
    return factorial(m + n - 2) / factorial(m - 1) / factorial(n - 1)

所以f(3, 2)返回: 3

并且f(7, 3)返回: 28

另一方面,如果您有兴趣生成唯一路径列表,您可以使用itertools.combinations执行与上述相同的操作; 也就是说,要找到可以在所有位置中放置D s(或R s)的位置:

from itertools import combinations
def f(m, n):
    for positions in map(set, combinations(range(m + n - 2), m - 1)):
        yield ''.join('DR'[i in positions] for i in range(m + n - 2))

以便:

print(*f(7, 3), sep='\n')

输出:

RRRRRRDD
RRRRRDRD
RRRRRDDR
RRRRDRRD
RRRRDRDR
RRRRDDRR
RRRDRRRD
RRRDRRDR
RRRDRDRR
RRRDDRRR
RRDRRRRD
RRDRRRDR
RRDRRDRR
RRDRDRRR
RRDDRRRR
RDRRRRRD
RDRRRRDR
RDRRRDRR
RDRRDRRR
RDRDRRRR
RDDRRRRR
DRRRRRRD
DRRRRRDR
DRRRRDRR
DRRRDRRR
DRRDRRRR
DRDRRRRR
DDRRRRRR

无论如何,这是一个非常低效的解决方案。 直接计算数字:

math.comb(m + n - 2, m - 1)

尝试使用 itertools.combinationss(step,4) 而不是 itertools.permutations(step,4)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM