解决这个问题的一种方法是不断通过注意到以下式子将数组数量逐一减少:
A0 × A1 × A2 = (A0 × A1) × A2
因此,您可以编写像这样的函数,它计算两个数组的笛卡尔积:
int[] cartesianProduct(int[] one, int[] two) {
int[] result = new int[one.length * two.length];
int index = 0;
for (int v1: one) {
for (int v2: two) {
result[index] = v1 * v2;
index++;
}
}
return result;
}
现在,您可以使用这个函数将数组对组合成一个包含整体笛卡尔积的单一数组。 伪代码如下:
While there is more than one array left:
Remove two arrays.
Compute their Cartesian product.
Add that array back into the list.
Output the last array.
而实际上,这就是Java:
Queue<int[]> worklist;
while (worklist.size() > 1) {
int[] first = worklist.remove();
int[] second = worklist.remove();
worklist.add(cartesianProduct(first, second));
}
int[] result = worklist.remove();
这种方法的问题是它使用与您生成的元素总数成比例的内存,这可能是一个非常庞大的数字!如果您只想逐个打印所有值而不存储它们,有一种更有效的方法。思路是可以开始列出在不同数组中的索引的所有可能组合,然后仅乘以这些位置处的值即可。一种方法是维护一个“索引数组”,其中指出要查看的下一个索引是什么。您可以通过与增加数字相同的方式“递增”数组来从一个索引移动到下一个索引。以下是相关代码:
int[] indexArray = new int[arrays.length];
mainLoop: while (true) {
int result = 1;
for (int i = 0; i < arrays.length; i++) {
result *= arrays[i][indexArray[i]]
}
System.out.println(result);
int index = 0;
while (true) {
indexArray[index]++;
if (indexArray[index] < arrays[i].length) break;
indexArray[index] = 0;
index ++;
if (index == indexArray.length) break mainLoop;
}
}
这个方法只使用 O(L) 的内存,其中 L 是你有的数组数量,但可能会生成指数级别多的值。
希望这能帮到你!