我发现这个问题很有趣,所以我最终花了一些时间来解决它。 :)
几个观察:
- 对每一行执行相同的组合,因此问题可以简化为组合一行的列,然后对每一行应用相同的方法。
- 您似乎不是在寻找 all 排列,而是寻找列与数组中后面的列组合的子集。 IE。你不想要
ab 和ba,只需要ab。
- 结果应包含 2..n-1 列的组合(其中 n 是列数)。 IE。您似乎不只想要 1 列(原始列)或 n 列(所有列的组合)。
如果我们根据观察来划分问题,找到解决方案会简单得多:
-
在一行中查找所有列的组合。这个问题也可以分为两部分:
a) 从 2..n-1(要组合的列数)迭代 - 我将其称为 level。也许不是最好的名字,但对我来说很有意义。
b) 找出当前level 的所有组合并将它们添加到结果中。
将此应用于数组中的每一行以生成最终结果数组。
如果这些观察结果给了您一些想法,您可能想停止阅读此处并自己尝试一下。自己解决这些问题比看一个完成的解决方案有趣得多。但是,如果您遇到困难 - 或者您已经解决了并且想要查看另一个(可能不同的)解决方案,请继续阅读。
算法
第 1 步:将列合并为一行。
a) 迭代级别 2..n-1。级别表示要组合的列数。
b) 求组合列的值。
请注意,第一列是从 0..n 级范围内选择的。范围 c1+1..n-level+1 中的第二个(其中 c1 是第一个选择的列的索引)。范围 c2+2..n-level+2 中的第三个。依此类推,直到我们添加了正确数量的列。
c) 将组合列的值添加到结果中。
第 2 步:将第 1 步应用到输入数组中的每一行。
a) 遍历输入数组中的每一行。
b) 将步骤 1 应用于该行。
c) 将结果行添加到输出数组。
实施
第 1 步:RowCombine
import java.util.ArrayList;
import java.util.List;
public class RowCombine {
String[] row;
List<String> result = new ArrayList<String>();
public RowCombine(String[] row) {
this.row = row;
}
public String[] combine() {
if (result.isEmpty()) {
for (int level = 2; level < row.length; level++) {
combine(level, 0, row.length - level, "");
}
}
return result.toArray(new String[result.size()]);
}
private void combine(int level, int lower, int upper, String value) {
if (level > 0) {
for (int c = lower; c <= upper; c++) {
combine(level - 1, c + 1, upper + 1, value + row[c]);
}
} else {
result.add(value);
}
}
}
第 2 步:ArrayCombine
public class ArrayCombine {
String[][] input;
String[][] output;
public ArrayCombine(String[][] input) {
this.input = input;
}
public String[][] combineColumns() {
if (output == null) {
output = new String[input.length][];
for (int i = 0; i < input.length; i++) {
RowCombine rowCombine = new RowCombine(input[i]);
output[i] = rowCombine.combine();
}
}
return output;
}
public void print() {
combineColumns();
for (String[] row : output) {
for (String value : row) {
System.out.print(value + ' ');
}
System.out.println();
}
}
}
测试
跑步
new ArrayCombine(new String[][]{
{ "a", "b", "c", "d"},
{ "1", "3", "9", "6"},
{ "4", "2", "7", "1"},
}).print();
生产
ab ac ad bc bd cd abc abd acd bcd
13 19 16 39 36 96 139 136 196 396
42 47 41 27 21 71 427 421 471 271
它也适用于更高的维度,例如:
new ArrayCombine(new String[][]{
{ "a", "b", "c", "d", "e"},
{ "1", "3", "9", "6", "5"},
{ "4", "2", "7", "1", "1"},
}).print();
生产
ab ac ad ae bc bd be cd ce de abc abd abe acd ace ade bcd bce bde cde abcd abce abde acde bcde
13 19 16 15 39 36 35 96 95 65 139 136 135 196 195 165 396 395 365 965 1396 1395 1365 1965 3965
42 47 41 41 27 21 21 71 71 11 427 421 421 471 471 411 271 271 211 711 4271 4271 4211 4711 2711