给出一个算法来查找给定n的括号的所有有效排列 例如:
for n=3, O/P should be
{}{}{}
{{{}}}
{{}}{}
{}{{}}
{{}{}}
答案 0 :(得分:106)
这是一个经典的组合问题,它以许多不同的方式表现出来。这些问题基本相同:
N
对括号(即此问题)N+1
因子N+1
叶这是一个简单的递归算法,用于解决Java中的这个问题:
public class Parenthesis {
static void brackets(int openStock, int closeStock, String s) {
if (openStock == 0 && closeStock == 0) {
System.out.println(s);
}
if (openStock > 0) {
brackets(openStock-1, closeStock+1, s + "<");
}
if (closeStock > 0) {
brackets(openStock, closeStock-1, s + ">");
}
}
public static void main(String[] args) {
brackets(3, 0, "");
}
}
以上打印(as seen on ideone.com):
<<<>>>
<<><>>
<<>><>
<><<>>
<><><>
基本上我们会跟踪有多少打开和关闭的括号“库存”供我们使用,因为我们正在递归地构建字符串。
请注意,如果您在尝试添加左括号之前交换递归的顺序,以便尝试添加一个紧密括号,则只需获得相同的平衡括号列表,但顺序相反! (see on ideone.com)。
上述解决方案非常简单明了,但可以进一步优化。
最重要的优化是在字符串构建方面。虽然它看起来像表面上的简单字符串连接,但上面的解决方案实际上有一个“隐藏的”O(N^2)
字符串构建组件(因为将一个字符连接到长度为String
的不可变N
是O(N)
操作)。一般来说,我们通过使用可变StringBuilder
来优化它,但对于这种特殊情况,我们也可以简单地使用固定大小的char[]
和index
变量。
我们还可以通过简化递归树进行优化。我们不是像在原始解决方案中那样递归“双向”,而是可以只递归“单向”,并以迭代方式执行“其他方式”。
在下文中,我们使用char[]
和index
代替String
进行了两种优化,并且仅递归添加开括号,迭代添加紧密括号:{{3 }}
public class Parenthesis2 {
public static void main(String[] args) {
brackets(4);
}
static void brackets(final int N) {
brackets(N, 0, 0, new char[N * 2]);
}
static void brackets(int openStock, int closeStock, int index, char[] arr) {
while (closeStock >= 0) {
if (openStock > 0) {
arr[index] = '<';
brackets(openStock-1, closeStock+1, index+1, arr);
}
if (closeStock-- > 0) {
arr[index++] = '>';
if (index == arr.length) {
System.out.println(arr);
}
}
}
}
}
递归逻辑现在不太明显,但这两种优化技术是有益的。
答案 1 :(得分:6)
答案 2 :(得分:2)
Eric Lippert最近在他的文章Every Tree There Is中发表了关于此事的博客。本文引用了上一篇文章Every Binary Tree There Is中编写的代码。
如果你可以枚举所有的二进制树,那么事实证明你可以列举所有解决方案来解决几十个不同的等价问题。
答案 3 :(得分:1)
Python中的非递归解决方案:
#! /usr/bin/python
def valid(state,N):
cnt=0
for i in xrange(N):
if cnt<0:
return False
if (state&(1<<i)):
cnt+=1
else:
cnt-=1
return (cnt==0)
def make_string(state,N):
ret=""
for i in xrange(N):
if state&(1<<i):
ret+='{'
else:
ret+='}'
return ret
def all_permuts(N):
N*=2
return [make_string(state,N) for state in xrange(1<<N) if valid(state,N)]
if __name__=='__main__':
print "\n".join(all_permuts(3))
这基本上检查[0,2 ^ n]中每个数字的二进制表示,将'1'视为'{',将'0'视为'}',然后仅过滤掉那些正确的数字均衡。