这个算法的空间复杂度是多少?

时间:2015-03-22 21:05:42

标签: algorithm recursion time-complexity space-complexity catalan

这是Cracking the Coding Interview(5 th edition)的问题9.6

实施算法以打印n对括号的所有有效组合
实施例
输入:3
输出:"((())),(()()),(())(),()(()),()()()"

这是我实现的算法(在Java中)

private static Set<String> getAllComb(int n) {
      Set<String> allPoss = new HashSet<String>();
      if(n>0) {
          if(n==1) {
              allPoss.add("()");
          } else {
              Set<String> before = getAllComb(n-1);
              for(String phrase: before) {
                  int length = phrase.length();
                  for(int start = length - 2; start>=0; start--) {
                      if(phrase.charAt(start) == '(') {
                          String phraseToConsider = phrase.substring(0, start+1) + "()" +
                               phrase.substring(start + 1);
                          if(!allPoss.contains(phraseToConsider)){
                              allPoss.add(phraseToConsider);
                          }
                      }
                  }
                  String phraseToConsider = "()" + phrase.substring(0);
                  if(!allPoss.contains(phraseToConsider)){
                      allPoss.add(phraseToConsider);
                  }
              }
          }
      }
      return allPoss;
}

这会产生正确的输出。我知道面试官(至少在亚马逊)喜欢问你解决方案的时间和空间复杂性。对于时间复杂度,我能够证明算法在具有递归关系的 O(n)中运行。我在分析空间复杂性方面遇到了麻烦。我这是一个递归解决方案,所以它至少应该是 O(n)但是在每次递归调用时,我也生成一个以n为界的集合。由于n个递归调用,总空间是 O(n)还是 O(n 2 因为设置的大小为每个递归调用n?

绑定n

2 个答案:

答案 0 :(得分:3)

  

对于时间复杂度,我能够证明算法在O(n)中以递归关系运行

这是错误的。平衡括号的序列数由Catalan numbers给出:指数多个这样的序列。你的算法不能是线性的,如果它也正确地解决问题,因为只输出指数数量的解决方案本身就是指数时间。

至于内存复杂性,您似乎在递归的每一步n - 1存储n的所有解决方案,因此内存复杂性对我来说也是指数级的,加上您创建的其他字符串和您在每个步骤中进行的递归调用,这只会增加复杂性。

您可以在不使用指数记忆的情况下解决问题:想想如何摆脱存储所有以前的序列。

答案 1 :(得分:1)

n 对正确匹配的括号的方法的数量是 n 加泰罗尼亚数,它实际上呈指数增长,而不是二次方。单独输出的空间复杂度为O(2 ^ n);请参阅the wikipedia article以快速了解加泰罗尼亚语数字。

请注意,您不是在每个深度进行一次递归调用,而是可能进行O(n)递归调用。