打印所有验证括号,这里的递归工作如何?

时间:2013-10-26 17:48:30

标签: java algorithm recursion

实施算法以打印n对括号的所有有效(例如,正确打开和关闭)组合。 例: 输入:3(例如,3对括号) 输出:()()(),()(()),(())(),((()))

答案是:

private static void printPar(int count)
{
    char[] str = new char[count*2];
    printPar(count,count,str, 0);
}

private static void printPar(int l, int r, char[] str, int count)
{
    if(l < 0 || r < l)
        return;

    if (l ==0 && r == 0)
    {
        System.out.println(str);
    }
    else
    {
        if (l > 0 )
        {
            str[count] = '(';
            printPar(l-1, r, str, count + 1);
        }

        if (r > 0)
        {
            str[count] = ')';
            printPar(l, r-1, str, count + 1);
        }
    }
}

但是我并不完全理解这个解决方案,尽管有人声称解释很简单。 (此代码工作正常)

在我看来,这段代码的工作原理是左括号更多,然后添加左括号。因此,只有((())的条件才能满足条件     if(l> 0) 出现在r&gt;之前0,所以,它应该总是首先处理所有左边的。

但是这段代码如何处理这种情况“()(())”?我调试这段代码,并在打印出“((()))”之后发现它。它进入了l = 1,r = 3和str =“((()))”和count = 2的情况。这对我来说没有意义。

另外,如果有人能解释时间/空间的复杂程度,那对我来说会很有帮助。

提前致谢。

3 个答案:

答案 0 :(得分:7)

我画了一棵树来展示如何为count = 3编写括号。每个节点代表一个函数调用,其文本为(),具体取决于调用函数的添加内容。叶子是打印它的调用。

由于此树的深度(显然)最多为2.count,因此空间复杂度为O(count)

由于每个函数调用都可以添加(),因此时间复杂度最多为O(2number of function calls) = O(22 count)

但是,由于调用是有条件的,时间复杂度最终会减少,更具体地说,它似乎在O(22 count/count)左右,尽管我还没有证明这一点。

答案 1 :(得分:3)

代码运行成功,因为它不会让r&lt;湖如果是这样,那么它只是丢弃组合并返回。这意味着右支架只能在左支架后出现。

复杂度的顺序,如果你计算丢弃的递归调用也是(2n)!/( n! * n! )。这是n'('和n')'的排列数。

如果您尝试跟踪代码,它将运行如下:

(
 (
  (
   )
    )
     ) 
      ((()))
  )
   (
    )
     )
      (()())
   )
    (
     )
      (())()
 )
  (
   (
    )
     )
      ()(())
(
 )
  (
   )
    (
     )
      ()()()

答案 2 :(得分:3)

在递归时,算法会跟踪剩余左括号的数量(l),剩余右括号的数量(r),到目前为止的结果(str)以及生成的括号数(count)。 / p>

如果没有括号,则会打印结果。

如果剩下至少一个左括号,则使用它,并且函数会递归以生成以当前前缀

开头的所有结果

然后,如果至少有一个右括号,并且至少有一个左括号没有关闭,则使用右括号,函数会递归。

  

但是这段代码如何处理这种情况“()(())”?我调试这段代码,   并在打印出“((()))”之后发现它。它去了   情况l = 1,r = 3,str =“((()))”和count = 2.这不是   对我有意义。

在打印((()))后,使用参数13((()))2调用该函数时,count=2表示str唯一有效的部分是((。然后,在使用参数)12(()进行递归之前,它会继续添加3,从而导致(()())为打印下一个组合,然后是()(())()()()