Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
本题主要考察DFS递归
Solution1
选择位置对新括号对儿进行插入,为了进行剪枝,判断当前括号字符串是否是回文串,如果是,可以减少一半的树枝。
class Solution {
public:
bool isPalindrome(string s) {
int l = 0, r = s.length() - 1;
while (l <= r) {
if (s[l] != s[r]) return false;
}
return true;
}
void dfs(string& cur, int depth, const int n, set<string>& results) {
if (depth == n) {
results.insert(cur);
return;
}
int start = 0, end = isPalindrome(cur) ? cur.length() / 2 : cur.length();
for (int i = start; i < end; i++) {
cur.insert(i, "()");
dfs(cur, depth + 1, n, results);
cur.erase(i, 2);
}
}
vector<string> generateParenthesis(int n) {
if (n <= 0) return {};
set<string> results;
string cur = "()";
dfs(cur, 1, n, results);
vector<string> ans(results.begin(), results.end());
return ans;
}
};
Solution2
对左右括号依次追加,当右括号的数目等于n
时到达递归边界,当左括号的数目大于右括号的数目时追加右括号,当左括号的数目小于n
时追加左括号。
class Solution {
public:
void dfs(int n, string cur, vector<string>& results, int left, int right) {
if (right == n) {
results.push_back(cur);
return;
}
if (left < n) {
dfs(n, cur + "(", results, left + 1, right);
}
if (right < left) {
dfs(n, cur + ")", results, left, right + 1);
}
}
vector<string> generateParenthesis(int n) {
vector<string> results;
string cur;
if (n > 0) dfs(n, cur, results, 0, 0);
return results;
}
};
比较
Solution1的用时要比Solution2多很多,主要原因是耗费在了回文串的判断和对字符串的插入上面,但是空间占用则少了很多,原因时Solution1的递归参数采用了引用型,避免了形参和实参的拷贝空间浪费。