昨天遇到了这样的一个问题:输入n(运行时可知)个数组(集合)A[a1,a2...an],数组(集合)长度为M[m1, m2...mn],要求输出这n个数组(集合)中每个元素的组合,输出的每个数组长度为n,数组的个数为m1*m2*...*mn。
第一次尝试:
思路:使用一个辅助pair数组,将输入的A的每个元素长度记录到first,second用于后续计数。然后使用循环遍历A中每个元素的每个组合。下面是伪代码:
arrays=[[],[],[],...]
counts=[[size a1,0],[size a2,0],[size a3,0],...]
complete = false
while !complete:
complete = True
for index=0; index < arrays.len; index+=1:
pos = counts[index][1]
countSize = counts[index][0]
if complete:
counts[index][1]+=1
complete=False
pos += 1
if pos >= (countSize):
complete=True
counts[index][1]=0
pos=0
print '%d\t', arrays[index][pos]
print '\n'
表现还可以,就是有一点不理想,常理上的第一个组合排到了最后一个位置。
第二次尝试:
思路:上面的代码把第一个组合放到后面的根本原因是在开始遍历时,我先置complete为true了,所以第一次pos就会加1。理由是我想给循环一个刺激点开始增长。折腾了很久,发现要把打印放到前面,顺序就对了。
...
for index=0; index < arrays.len; index+=1:
pos = counts[index][1]
countSize = counts[index][0]
print '%d\t', arrays[index][pos]
...
WCS同学看不下去了,觉得前面的好难读,给了我如下代码。
public class FreeMain {
public static void main(String[] args){
Object[][] values=new Object[][]{{"a","b","c","d","e","f"},{"11","22","33","44","66"},{"&","$","!","*"}};
int[] symbol=new int[values.length];
Arrays.fill(symbol,0);
while(symbol[0] <values[0].length){
StringBuilder str=new StringBuilder();
for(int i=0;i<symbol.length;i++){
str.append(values[i][symbol[i]]).append(" ");
}
System.out.println(str);
symbol[symbol.length-1]++;
for(int j=symbol.length-1;j>=0;j--){
if(symbol[j]>=values[j].length && j>0){
symbol[j]=0;
symbol[j-1]++;
}
}
}
}
}