我想找到n
个项目可以在m
个分箱之间拆分的所有方法。例如,对于n=3
和m=3
,输出将是(顺序无关紧要):
[3 0 0
0 3 0
0 0 3
2 1 0
1 2 0
0 1 2
0 2 1
1 0 2
2 0 1
1 1 1]
算法应尽可能高效,最好使用内置函数而不是for
循环进行矢量化/使用。谢谢!
答案 0 :(得分:7)
这应该非常有效。
它的工作原理是在 m -1整数值,可能是重合的分裂点生成实际区间[0, n ]的所有可能的分割。结果子区间的长度给出了解决方案。
例如,对于n=4
和m=3
,在 m -1点分割区间[0,4]的一些可能方法是:
0
,0
分割:这会给出长度0
,0
,4
的子区间。0
,1
分割:这会给出长度0
,1
,3
的子区间。4
,4
分割:这会给出长度4
,0
,0
的子区间。代码:
n = 4; % number of items
m = 3; % number of bins
x = bsxfun(@minus, nchoosek(0:n+m-2,m-1), 0:m-2); % split points
x = [zeros(size(x,1),1) x n*ones(size(x,1),1)]; % add start and end of interval [0, n]
result = diff(x.').'; % compute subinterval lengths
结果按字典顺序排列。
例如,对于n = 4
个分区中的m = 3
项,输出为
result =
0 0 4
0 1 3
0 2 2
0 3 1
0 4 0
1 0 3
1 1 2
1 2 1
1 3 0
2 0 2
2 1 1
2 2 0
3 0 1
3 1 0
4 0 0
答案 1 :(得分:1)
我想建议一个基于外部函数和accumarray
的解决方案(由于repelem
,它应该可以在R2015a开始工作):
n = uint8(4); % number of items
m = uint8(3); % number of bins
whichBin = VChooseKR(1:m,n).'; % see FEX link below. Transpose saves us a `reshape()` later.
result = accumarray([repelem(1:size(whichBin,2),n).' whichBin(:)],1);
其中VChooseKR(V,K)
创建一个矩阵,其行是通过重复选择向量K
的{{1}}元素而创建的所有组合。
V
和VChooseKR(1:m,n)
的{{1}}输出为:
m=3
我们现在需要做的就是" histcount"每行使用正整数二进制数来获得所需的结果。第一个输出行是n=4
,因为所有4个元素都在1 st bin中。第二行是 1 1 1 1
1 1 1 2
1 1 1 3
1 1 2 2
1 1 2 3
1 1 3 3
1 2 2 2
1 2 2 3
1 2 3 3
1 3 3 3
2 2 2 2
2 2 2 3
2 2 3 3
2 3 3 3
3 3 3 3
,因为3个元素位于1 st bin中,1个位于2 nd 等中。