我对一个众所周知的问题的堆栈状态有点困惑 ,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 + ")");
}
}
如果我为此代码绘制一个递归树是
但我不清楚每个子树如何正确启动。
例如,在下图中最左边的子树后,
它上升到((
,然后开始第二个最左边的子树(()
,...
我在下面绘制了递归树的堆栈状态的一部分。
1.我的第一个问题是堆栈如何仅在第一个堆栈中弹出(((
(1)
对应于上升树然后开始堆栈中第二个最左边的子树(2)
在代码?
为什么堆栈不会弹出其他内容,例如((()
或((())
或(
在给定代码的第一个堆栈(1)中?
也许我还没有清楚地理解递归和回溯是如何工作的。
2.他们说这个问题正在使用回溯。 如果某个条件在去之前没有遇到,则会发生回溯 进一步下到一棵焚烧树,它不会穿着长袍而只是分叉出来 像N-Queen问题一样的不同子树。
即使这个问题没有这样的条件可以停止下到递归树。 这怎么称为回溯问题?
答案 0 :(得分:0)
如果您仔细跟踪执行情况,您会发现堆栈 会弹出到((())
,然后转到((()
,然后转到(((
,最后((
......这是第二个选择(可能的分支)的最早点。请记住n=3
:当您第一次回溯到((())
时,您已经处理过添加RPAREN,并且没有更多LPARENS可用 - 您已经使用了全部三个。同样,你必须将堆栈移回((
,在那里你可以最终做出与你刚刚处理的((()))
分支不同的选择:你刚刚弹出第三个LPAREN,现在你可以用一个RPAREN代替它,并向下一个新的分支。