我有C列,我想填充N个元素的所有组合(C> N)。我怎么能在Matlab中做到这一点? 示例:C = 5,N = 3;那么N的所有组合从1到N,即1到3,以C = 5列填充。我试过NchooseK但是无法做到这一点。预期输出如下:
输出:11111,
11112,
11122,
11222,
......,
22222,
22223,
22233,
......,
33333,
.....
12312,
12313,
12323,
......等......
以这种方式,1到N的所有组合填充到C列。我的C可以大到40,N可以是10.
Matlab有没有办法。
答案 0 :(得分:1)
这是一个树遍历问题。这是一个DFS方法:
function s = GetCombinations(C,N)
C = int64(C);
N = int64(N);
assert(C>0 && N>0, 'Invalid input')
s = prtstr(C,N,''); % wrap the iterative function
end
function s = prtstr(C,N,prefix)
s = cell(N^C,1);
if C == 1
for ii = 1:N
s{ii} = [prefix, num2str(ii)];
end
else
BlockLen = N^(C-1);
for ii = 1:N
s((1+(ii-1)*BlockLen) : (ii*BlockLen)) = ....
prtstr(C-1,N,[prefix, num2str(ii)]);
end
end
end
输出是包含所有组合字符串的单元格向量。
>> s = GetCombinations(5,3)
s =
'11111'
'11112'
'11113'
'11121'
'11122'
'11123'
'11131'
'11132'
'11133'
'11211'
'11212'
'11213'
'11221'
'11222'
'11223'
'11231'
'11232'
....
编辑:跳过重复的案例。例如,11112
和11121
被认为是相同的,只列出第一个。
function s = GetCombinations(C,N)
C = int64(C);
N = int64(N);
assert(C>0 && N>0, 'Invalid input')
s = prtstr(C,N,'',1);
s = s(~cellfun(@isempty,s));
end
function s = prtstr(C,N,prefix,startN)
s = cell(N^C,1);
if C == 1
for ii = startN:N
s{ii} = [prefix, num2str(ii)];
end
else
BlockLen = N^(C-1);
for ii = startN:N
s((1+(ii-1)*BlockLen) : (ii*BlockLen)) = ....
prtstr(C-1,N,[prefix, num2str(ii)], ii);
end
end
end
>> s = GetCombinations(5, 3)
s =
'11111'
'11112'
'11113'
'11122'
'11123'
'11133'
'11222'
'11223'
'11233'
'11333'
'12222'
'12223'
'12233'
'12333'
'13333'
'22222'
'22223'
'22233'
'22333'
'23333'
'33333'
编辑:对于大型C
和N
,预先分配单元格数组是不可行的。事实上,大多数细胞都是空的。哪些是空的可以预先确定,但这本身就是一个有趣的问题。然而,我只是在移动时附加单元阵列而不是预先分配它。所以有点慢,但它的工作原理。
function s = GetCombinations(C,N)
C = int64(C);
N = int64(N);
assert(C>0 && N>0, 'Invalid input')
s = prtstr(C,N,'',1);
s = s(~cellfun(@isempty,s));
end
function s = prtstr(C,N,prefix,startN)
s = cell(0,1);
if C == 1
nt = N-startN+1;
t = cell(nt,1);
for ii = 1:nt
t{ii} = [prefix, num2str(ii+startN-1)];
end
s = t;
else
for ii = startN:N
t = prtstr(C-1,N,[prefix, num2str(ii)], ii);
s = [s;t];
end
end
end
编辑:无记忆版本。
请求(C,N) = (20,10)
并且结果太大而无法保存在内存中。一种可能的解决方案是只打印出结果而不存储它。下面是经过测试的代码。
function GetCombinations(C,N, fh)
C = int64(C);
N = int64(N);
assert(C>0 && N>0, 'Invalid input')
prtstr(C,N,'',1, fh);
end
function prtstr(C,N,prefix,startN, fh)
if isempty(fh) % assign fh = [] if you do not want text file output
fh = 1; % print to command window
end
if C == 1
for ii = 1:N-startN+1
fprintf(fh, '%s%d\n', prefix, ii+startN-1);
end
else
for ii = startN:N
prtstr(C-1,N,[prefix, num2str(ii)], ii, fh)
end
end
end
该函数接受一个额外的输入参数fh
,它是一个文件句柄。因为(20,10)
有很多输出行(10m +行和200MB +),所以您可能希望将结果直接打印到文本文件中。为实现这一目标,
fh = fopen('testout.txt','w');
GetCombinations(20,10,fh)
fclose(fh)
否则,如果您确实要将结果打印到命令窗口,请使用
GetCombinations(20,10,[])