我感兴趣的n个阵列执行笛卡尔乘积。 如果我知道阵列数量的时间提前我可以编写代码。 例如,给定2个数组:
int[] a = new int[]{1,2,3};
int[] b = new int[]{1,2,3};
for(int i=0; i<=a.length; i++){
for(int j=0; j<=b.length; j++){
System.out.println(a[i]*b[j]);
}
}
问题是,在运行时,我不知道阵列的数量。 我可以具有2个阵列,或我可以具有100个阵列。 有没有一种方法,我可以做到这一点? 谢谢!
解决这个问题的一种方法是通过注意到在时间不断降低阵列之一的数
A 0×A 1×A 2 =(A 0×A 1)×A 2
因此,你可以写这样的一个,其计算两个数组的笛卡儿积函数:
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;
/* fill the worklist with your arrays; error if there are no arrays. */
while (worklist.size() > 1) {
int[] first = worklist.remove();
int[] second = worklist.remove();
worklist.add(cartesianProduct(first, second));
}
/* Obtain the result. */
int[] result = worklist.remove();
这种方法的问题是,它使用的内存比例给你生产要素的总数。 这是一个非常庞大的数字! 如果你只是想打印所有的值了一个在同一时间而不存储它们,有一个更有效的方法。 这个想法是,你可以启动上市关在不同的阵列指数的所有可能的组合,然后随便去在那些位置乘值加在一起。 这样做的一个办法是维持一个“索引数组”说什么的下一个指数看就是。 您可以从一个指数“递增”的数组,你会增加一些同样的方式移动到下一个。 下面是一些代码:
int[] indexArray = new int[arrays.length];
mainLoop: while (true) {
/* Compute this entry. */
int result = 1;
for (int i = 0; i < arrays.length; i++) {
result *= arrays[i][indexArray[i]]
}
System.out.println(result);
/* Increment the index array. */
int index = 0;
while (true) {
/* See if we can bump this array index to the next value. If so, great!
* We're done.
*/
indexArray[index]++;
if (indexArray[index] < arrays[i].length) break;
/* Otherwise, overflow has occurred. If this is the very last array, we're
* done.
*/
indexArray[index] = 0;
index ++;
if (index == indexArray.length) break mainLoop;
}
}
这种仅使用O(L)存储器,其中L是你有阵列的数量,但会产生潜在的许多呈指数值。
希望这可以帮助!
您可以使用递归代替迭代 - 但要小心 - 可能会出现StackOverflowException。