【探索-中級演算法】生成括號
阿新 • • 發佈:2018-11-14
得到全排列的組合,同時對於不符合要求的組合要剔除。
public List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
recall("", n, n,result);
return result;
}
/**
* @param leftCount 剩餘可用的左括號個數
* @param rightCount 剩餘可用的右括號個數
*/
public void recall(String s, int leftCount, int rightCount,List<String> result) {
// 沒有括號可以進行組合了
if (leftCount == 0 && rightCount == 0) {
result.add(s);
} else {
if (leftCount>0) {
String tmp = s + '(';
int newLeftCount = leftCount - 1;
if (newLeftCount==rightCount) {
// 當左右括號已經使用了同樣的個數,且目前為止組成的組合有效的話,
// 才繼續遞迴,(剪枝,但是也增加了判斷的時間成本)
// 因為有了這一步判斷,則當 leftCount 和 rightCount 都為 0 時肯定
// 是符合條件的
if (isEffective(tmp)) recall(tmp, newLeftCount, rightCount,result);
} else {
recall (s + '(', newLeftCount, rightCount,result);
}
}
if (rightCount>0) {
String tmp = s + ')';
int newRightCount = rightCount - 1;
if (newRightCount==leftCount) {
if (isEffective(tmp)) recall(tmp, leftCount, newRightCount,result);
} else {
recall(tmp, leftCount, newRightCount,result);
}
}
}
}
// 判斷組合是不是有效的
// 有效的定義就是對於 s[i] 如果是 '(',則在 s[j>i] 要存在 ')' 與之匹配
public boolean isEffective(String s) {
if (s!=null&&s.length()>0) {
Stack<Character> stack = new Stack<>();
char[] chars = s.toCharArray();
for (char c : chars) {
if (c=='(') stack.push('(');
else {
if (stack.isEmpty()) return false;
else stack.pop();
}
}
return true;
}
return false;
}
根據網站提交記錄進一步的優化:
public List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
recall(n, n,"",result);
return result;
}
/**
* @param leftCount 剩餘可用的左括號個數
* @param rightCount 剩餘可用的右括號個數
*/
public void recall(int leftCount,int rightCount,String s,List<String> result) {
if (leftCount == 0 && rightCount == 0) {
result.add(s);
}
if (leftCount>0) recall(leftCount - 1, rightCount, s + '(', result);
if (rightCount>leftCount) recall(leftCount, rightCount - 1, s + ')', result);
}
可以發現,肯定是要先用 ‘(’
,然後才能用 ')'
與前面的 '('
匹配。