题目
原文:
Implement an algorithm to print all valid (e.g., properly opened and closed) combinations of n-pairs of parentheses.
EXAMPLE:
input: 3 (e.g., 3 pairs of parentheses)
output: ()()(), ()(()), (())(), ((())),(()())
译文:
实现一个算法打印n对圆括号的所有有效组合(括号的左右匹配)
例如:
输入:3(3对括号)
输出:()()(), ()(()), (())(), ((())),(()())
解答
此题由递归算法,分析如下:
当输入数字num=1时,输出圆括号的有效组合为:();
num=2时,可以在num=1的基础上对括号进行插空处理,则得到:()(),(()),()()——去掉一个重复的()()
同理,num=3时,得到:对()()进行插空:()()(),(())(),()()(),()(()),()()()
对(())进行插空:()(()),(()()),((())),(()()),(())()
去掉重复的得:()()(),(())(),()(()),(()()),((()))……
所以用HashSet来存储找到的有效组合,防止出现重复,代码如下:
public static void printPare(int num){
HashSet<String> parestr=findPareStr(num);
Iterator<String> it=parestr.iterator();
while(it.hasNext()){
String substr=it.next();
System.out.println(substr);
}
}
public static HashSet<String> findPareStr(int num){
HashSet<String> pare=new HashSet<String>();
if(num==1){
pare.add("()");
return pare;
}
HashSet<String> subpare=findPareStr(num-1);
Iterator<String> it=subpare.iterator();
while(it.hasNext()){
String substr=it.next();
for(int i=0;i<=substr.length();i++){
String tempstr=insertStr(substr,i,"()");
pare.add(tempstr);
}
}
return pare;
}
//在指定位置插入一个字符
public static String insertStr(String target,int index,String str){
String targetStr="";
if(index==0) targetStr=str+target;
else if(index==target.length()) targetStr=target+str;
else targetStr=target.substring(0,index)+str+target.substring(index);
return targetStr;
}
另外一种递归方法比较巧妙,分析如下:
有效的组合表现为:左括号的数量在组合的任意子串上大于等于右括号的数量
((())) left=3 right3
( left=1 right=0
(( left=2 right=0
((( left=3 right=0
((() left=3 right=1
((()) left=3 right=2
((())) left=3 right=3
从上述过程,可以发现在没有左右括号时,字符串被构建完成,直接输出;如果有一个左括号可用,那么尝试加入字符串;当有了一个左括号后,需要加入一个右括号,以保持"平衡";如果有一个右括号可用,那么尝试加入字符串中。这道题目的递归公式应用的很巧妙,当退出一层递归后,代码继续向下运行,就又进入到一层递归中,此时也就可以满足另外一种情况。代码如下:
public static void printPare1(int openStock, int closeStock, String s) {
if (openStock == 0 && closeStock == 0) {
System.out.println(s);
}
if (openStock > 0) {
printPare1(openStock-1, closeStock+1, s + "(");
}
if (closeStock > 0) {
printPare1(openStock, closeStock-1, s + ")");
}
}
完整代码如下:
import java.util.HashSet;
import java.util.Iterator;
class Q8_5{
public static void printPare(int num){
HashSet<String> parestr=findPareStr(num);
Iterator<String> it=parestr.iterator();
while(it.hasNext()){
String substr=it.next();
System.out.println(substr);
}
}
public static HashSet<String> findPareStr(int num){
HashSet<String> pare=new HashSet<String>();
if(num==1){
pare.add("()");
return pare;
}
HashSet<String> subpare=findPareStr(num-1);
Iterator<String> it=subpare.iterator();
while(it.hasNext()){
String substr=it.next();
for(int i=0;i<=substr.length();i++){
String tempstr=insertStr(substr,i,"()");
pare.add(tempstr);
}
}
return pare;
}
//在指定位置插入一个字符
public static String insertStr(String target,int index,String str){
String targetStr="";
if(index==0) targetStr=str+target;
else if(index==target.length()) targetStr=target+str;
else targetStr=target.substring(0,index)+str+target.substring(index);
return targetStr;
}
//方法二
public static void printPare1(int openStock, int closeStock, String s) {
if (openStock == 0 && closeStock == 0) {
System.out.println(s);
}
if (openStock > 0) {
printPare1(openStock-1, closeStock+1, s + "(");
}
if (closeStock > 0) {
printPare1(openStock, closeStock-1, s + ")");
}
}
public static void main(String[] args){
printPare(3);
System.out.println("");
printPare1(3,0,"");
}
}
---EOF---