给定元素集的唯一(有限长度)组合 - Matlab 中的实现

Posted

技术标签:

【中文标题】给定元素集的唯一(有限长度)组合 - Matlab 中的实现【英文标题】:Unique (finite length) combinations of a given set of elements - Implementation in Matlab 【发布时间】:2015-01-19 15:05:04 【问题描述】:

我有以下问题。我需要重现 0 和 1 的所有独特组合,其中包括正好 m 个零和正好 n 个。例如,如果我有 2 个 0 和 3 个 1,我正在寻找的组合是以下 10 个:

1) 0 0 1 1 1

2) 0 1 0 1 1

3) 0 1 1 0 1

4) 0 1 1 1 0

5) 1 0 0 1 1

6) 1 0 1 0 1

7) 1 0 1 1 0

8) 1 1 0 0 1

9) 1 1 0 1 0

10) 1 1 1 0 0

现在,我使用 A=perms([0 0 1 1 1]) 然后 unique(A,'rows') 但是如果向量的长度超过 10,这真的很耗时。任何人都可以想出更有效的解决方案?

【问题讨论】:

【参考方案1】:

方法一

    从集合[0 1] 中生成m+n 元素的所有“组合”。这可以使用this approach 有效地完成。

    只保留那些包含n 的组合。

代码:

m = 7; %// number of zeros
n = 9; %// number of ones
L = m+n;
vectors = repmat([0 1], 1, L);
combs = cell(1,L);
[combsend:-1:1] = ndgrid(vectorsend:-1:1);
combs = cat(L+1, combs:);
combs = reshape(combs,[],L);
combs = combs(sum(combs,2)==n,:);

m=2; n=3 的示例结果:

combs =
     0     0     1     1     1
     0     1     0     1     1
     0     1     1     0     1
     0     1     1     1     0
     1     0     0     1     1
     1     0     1     0     1
     1     0     1     1     0
     1     1     0     0     1
     1     1     0     1     0
     1     1     1     0     0

方法 1 已修改

要节省内存,请在第 1 步中使用 uint8 值,并在第 2 步结束时转换为 double

m = 7; %// number of zeros
n = 9; %// number of ones
L = m+n;
vectors = repmat(uint8([0 1]), 1, L);
combs = cell(1,L);
[combsend:-1:1] = ndgrid(vectorsend:-1:1);
combs = cat(L+1, combs:);
combs = reshape(combs,[],L);
combs = double(combs(sum(combs,2)==n,:));

方法2

类似于方法 1,但在步骤 1 中,使用 dec2bin 将所有组合生成为从 02^(m+n)-1 的所有整数的二进制表达式。这会产生一个char 数组,因此它应该与修改方法 1 一样具有内存效率。那么,第2步应该稍微适应一下使用chars,最后需要转换成数值:

m = 7; %// number of zeros
n = 9; %// number of ones
combs = dec2bin(0:2^(m+n)-1);
combs = combs(sum(combs=='1',2)==n,:)-'0';

【讨论】:

以上是关于给定元素集的唯一(有限长度)组合 - Matlab 中的实现的主要内容,如果未能解决你的问题,请参考以下文章

最优化模型及分类

生成长度在给定范围内的数组的所有可能组合

在 MATLAB 中读取 HDF5 数据集的一些特定元素

含有重复字符的字符串排列组合

生成函数

查找与排序:计数排序