Skip to main content
 首页 » 编程设计

python之如何计算满足给定条件的向量的所有排列

2025年05月04日17TianFang

我想一次计算向量 N 的所有排列 k。我还想允许 N 的任何元素与其自身置换,而不仅仅是与其他元素置换。我只想获得总和为给定数字 n 的排列。

这是 MATLAB 中的一个例子:

N = [1 2 3 4]; 
k = 2; 
n = 6; 

对于上面的数字,我可以通过以下方式达到我的目标:

Perm = combvec(N, N)'; 
Perm = Perm(sum(Perm,2)==n,:); 
Perm = 
 
     4     2 
     3     3 
     2     4 

但是,N 预计最多 90 个元素,k 的值最多 10 .这使得上述方法不可行,因为它涉及计算许多不需要的排列。

在给定预期的 N 向量长度和 k 的情况下,是否有任何方法可以有效地执行此操作?我很乐意考虑使用 MATLAB、R 或 Python 的解决方案。

请您参考如下方法:

这是一种基于生成器的尝试,一次只生成一个排列,而不是尝试将它们全部存储在内存中。我采用了生成器方法,因为我认为使用其他任何方法都会耗尽内存,只要 k 超过 5,排列的数量就会很大:

def find_perm(k, n, N=None): 
    # Initialize N 
    if N is None: 
        N = list(range(1, n - k + 1)) 
 
    if k == 0: 
        return [] 
 
    # Only search up to n (the current target) 
    for i in N[:(n + 1)]: 
        if i > n: 
            continue 
        if i == n: 
            yield [i] 
            continue 
        # Recurse 
        sub_perms = find_perm(k - 1, n - i, N[:(n + 1)]) 
 
        for sub_perm in sub_perms: 
            perm = [i] + sub_perm 
            if sum(perm) == n: 
                yield perm 

示例输出:

list(find_perm(2, 6)) 
# [[2, 4], [3, 3], [4, 2]] 
 
# Too many to store, just printing a few 
big_perms = find_perm(10, 100) 
for i in range(5): 
    print(next(big_perms)) 
# [1, 1, 1, 1, 1, 1, 1, 1, 2, 90] 
# [1, 1, 1, 1, 1, 1, 1, 1, 3, 89] 
# [1, 1, 1, 1, 1, 1, 1, 1, 4, 88] 
# [1, 1, 1, 1, 1, 1, 1, 1, 5, 87] 
# [1, 1, 1, 1, 1, 1, 1, 1, 6, 86]