Cracking the coding interview--Q8.5

题目

原文:

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---

你可能感兴趣的:(Cracking the coding interview--Q8.5)