题目
原文:
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---