打印所有有效括号给定的数字n

时间:2017-10-31 12:58:05

标签: algorithm recursion

我对一个众所周知的问题的堆栈状态有点困惑 ,Valid Permutation of Parenthesis

互联网上有很多文章和解决方案,其中一个简单的解决方案是

static void allParen1( int l, int r, int n, String str ) {
    if( r == n ) {
        System.out.println(str + " <" + l + ": " + r + ">");
        return;
    }

    if( l < n ) {
        allParen1( l + 1, r, n, str +"(" );
    } 

    if( r < l ) {
        allParen1( l, r + 1, n, str + ")");
    }
}

如果我为此代码绘制一个递归树是

enter image description here

但我不清楚每个子树如何正确启动。

例如,在下图中最左边的子树后, 它上升到((,然后开始第二个最左边的子树((),...

我在下面绘制了递归树的堆栈状态的一部分。

enter image description here 1.我的第一个问题是堆栈如何仅在第一个堆栈中弹出((((1) 对应于上升树然后开始堆栈中第二个最左边的子树(2) 在代码?

为什么堆栈不会弹出其他内容,例如((()((())( 在给定代码的第一个堆栈(1)中?

也许我还没有清楚地理解递归和回溯是如何工作的。

2.他们说这个问题正在使用回溯。 如果某个条件在去之前没有遇到,则会发生回溯 进一步下到一棵焚烧树,它不会穿着长袍而只是分叉出来 像N-Queen问题一样的不同子树。

即使这个问题没有这样的条件可以停止下到递归树。 这怎么称为回溯问题?

1 个答案:

答案 0 :(得分:0)

如果您仔细跟踪执行情况,您会发现堆栈 会弹出到((()),然后转到(((),然后转到((( ,最后(( ......这是第二个选择(可能的分支)的最早点。请记住n=3:当您第一次回溯到((())时,您已经处理过添加RPAREN,并且没有更多LPARENS可用 - 您已经使用了全部三个。同样,你必须将堆栈移回((,在那里你可以最终做出与你刚刚处理的((()))分支不同的选择:你刚刚弹出第三个LPAREN,现在你可以用一个RPAREN代替它,并向下一个新的分支。