1. 程式人生 > >9.9遞歸和動態規劃(六)——打印n對括號的所有有效組合(即左右括號正確配對)

9.9遞歸和動態規劃(六)——打印n對括號的所有有效組合(即左右括號正確配對)

思路 即使 情況 else 字符 ram 配對 字符串 pop

/**
* 功能:打印n對括號的所有有效組合(即左右括號正確配對)。

*/


兩種方法:

方法一:

	/**
	 * 思路:在括號的最前面或者原有的每對括號中面插入一對括號。

至於其它任何位置。比方字符串的末尾,都會跟之前的情況反復。 * 註意:將字符串放進結果列表之前。必須檢查列表有無反復。 * @param remaining * @return */ public static HashSet<String> generateParens(int remaining){ HashSet<String> set=new HashSet<String>(); if(remaining==0) set.add(""); else{ HashSet<String> prev=generateParens(remaining-1); for(String str:prev){ //括號內插入 for(int i=0;i<str.length();i++){ if(str.charAt(i)=='('){ String s=insertInside(str,i); set.add(s);//插入元素之前,HashSet會自己主動檢查有無反復 } } //括號最前面插入 if(!set.contains("()"+str)) set.add("()"+str); } } return set; } /** * 在每對括號內插入 * @param str * @param leftIndex * @return */ public static String insertInside(String str,int leftIndex){ String left=str.substring(0,leftIndex+1);//左括號之後插入括號,所以須要leftIndex+1 String right=str.substring(leftIndex+1); return left+"()"+right; }


方法二:

	/**
	 * 思路:從頭開始構造字符串,避免出現反復字符串。註意增加左括號和右括號,僅僅要字符串仍然有效。
	 * 每次遞歸調用,都有一個索引指向字符串的某個字符。選擇左括號和右括號:
	 * 		1)左括號:僅僅要左括號還沒實用完,就能夠插入左括號。

* 2)右括號:僅僅要不造成語法錯誤,就能夠插入右括號(右括號比左括號多。即語法錯誤)。 * 因此。僅僅需記錄同意插入的左右括號數目。假設還有左括號可用。就插入一個左括號。然後遞歸。 * 假設後括號比左括號多,(即使用中的左括號比右括號多)。就插入一個右括號,然後遞歸。

* * 在字符串的每個索引相應位置插入左括號和右括號。並且絕對不會反復索引!!! * @param count * @return */ public static ArrayList<String> generateParens2(int count){ ArrayList<String> list=new ArrayList<String>(); char[] str=new char[count*2]; addParens(list,count,count,str,0); return list; } public static void addParens(ArrayList<String> list, int leftRem, int rightRem, char[] str, int count) { // TODO Auto-generated method stub if(leftRem<0||rightRem<leftRem) return; if(leftRem==0&&rightRem==0){ String s=String.copyValueOf(str); list.add(s); } if(leftRem>0){ str[count]='('; addParens(list, leftRem-1, rightRem, str, count+1); } if(rightRem>leftRem){ str[count]=')'; addParens(list, leftRem, rightRem-1, str, count+1); } }



9.9遞歸和動態規劃(六)——打印n對括號的所有有效組合(即左右括號正確配對)