查找数组数组的笛卡尔积的时间复杂度

时间:2018-04-22 14:35:30

标签: java performance time-complexity cartesian-product

final class Combination {

    public static void findCombinations(String[][] sets) {
        int combinations = 1;
        for(int i = 0; i < sets.length; combinations *= sets[i].length, i++);
        for(int i = 0; i < combinations; i++) {
            int j = 1;
            for(String[] set : sets) {
                System.out.print(set[(i/j)%set.length] + " ");
                j *= set.length;
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
         findCombinations(new String[][]{{"a","b","c"}, {"d","e","i"}, {"f","g","h"}});
    }
  }

我的回答看起来像这样

   a d f 
   b d f 
   c d f 
   a e f 
   b e f 
   c e f 
   a i f 
   b i f 
   c i f 
   a d g 
   b d g 
   c d g 
   a e g 
   b e g 
   c e g 
   a i g 
   b i g 
   c i g 
   a d h 
   b d h 
   c d h 
   a e h 
   b e h 
   c e h 
   a i h 
   b i h 
   c i h 

我想知道我的解决方案的时间复杂性以及是否有任何方法可以改进解决方案。

1 个答案:

答案 0 :(得分:1)

显然O(|first| * |second| * |third| * ...)并且你无法改善该绑定,Theta,而不仅仅是O

仅结果是大(在您的示例中为27 = 3 * 3 * 3),您需要创建每个结果,这样您才能获得比结果大小更好的结果。结论是Omega绑定。

O部分非常明显,因为您的代码执行的所有子操作都在Theta(1)中。所以我们只需要考虑循环。你最内层的循环生成结果,每个结果得到一个打印。因此,您的算法是最佳的,每个正确结果一次迭代。你不会产生无用的对,你需要丢弃它们或使用它们之间的任何非常数运算。由于单独的结果数量是上述复杂程度,因此您的代码也是如此。

对于精确的边界,我们需要包括每个子元素的大小,如前所述。但是如果你想要一个大小的变量,让我们说n你可以用最大数组的大小限制其他大小:

n = max(|first|, |second|, |third|, ...)

然后你得到

Theta(n^x)

其中x是您传入的数组的数量。因此,在您的示例中,它将是Theta(n^3)