我想一次计算向量 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]
