Dare2Solve
The task is to generate all combinations of well-formed parentheses given n
pairs of parentheses. Each combination should be a string with exactly n
pairs of open and close parentheses, arranged in a valid manner.
For example, given n = 3
, the valid combinations are:
((()))
(()())
(())()
()(())
()()()
The problem can be approached using recursive backtracking. We need to ensure that at every step of adding a parenthesis, the resulting string remains valid. This involves keeping track of the number of open and close parentheses used.
The main idea is to use recursion to explore all possible ways of adding parentheses:
Initialization: Begin with an empty string and zero counts for both open and close parentheses. Initialize a list to store the results.
Recursive Function: Define a recursive function that takes the current state of the string, the counts of open and close parentheses, and the maximum number of pairs.
2 * n
), add it to the results.n
, recursively add an open parenthesis and continue.Return Results: After the recursive function completes, return the list of valid combinations.
O(4^n / sqrt(n))
The time complexity is derived from the fact that the number of valid combinations grows exponentially with n
. The Catalan number C(n)
describes the number of valid combinations and can be approximated by 4^n / sqrt(n)
.
O(4^n / sqrt(n))
Space complexity includes the space required for storing the result and the depth of the recursion stack. Since each valid combination is stored and there can be up to 4^n / sqrt(n)
valid combinations, the space complexity reflects this growth.
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> result;
generate(result, "", 0, 0, n);
return result;
}
private:
void generate(vector<string>& result, string current, int open, int close, int max) {
if (current.length() == max * 2) {
result.push_back(current);
return;
}
if (open < max) {
generate(result, current + "(", open + 1, close, max);
}
if (close < open) {
generate(result, current + ")", open, close + 1, max);
}
}
};
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
result = []
self._generate(result, "", 0, 0, n)
return result
def _generate(self, result: List[str], current: str, open_count: int, close_count: int, max: int):
if len(current) == max * 2:
result.append(current)
return
if open_count < max:
self._generate(result, current + "(", open_count + 1, close_count, max)
if close_count < open_count:
self._generate(result, current + ")", open_count, close_count + 1, max)
public class Solution {
public List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
generate(result, "", 0, 0, n);
return result;
}
private void generate(List<String> result, String current, int open, int close, int max) {
if (current.length() == max * 2) {
result.add(current);
return;
}
if (open < max) {
generate(result, current + "(", open + 1, close, max);
}
if (close < open) {
generate(result, current + ")", open, close + 1, max);
}
}
public static void main(String[] args) {
Solution solution = new Solution();
int n = 3;
List<String> result = solution.generateParenthesis(n);
for (String s : result) {
System.out.println(s);
}
}
}
var generateParenthesis = function (n) {
function generate(x) {
var choice = ["(", ")"];
if (x === 1) {
return choice;
} else {
var temp = generate(x - 1);
var res = [];
for (let i = 0; i < choice.length; i++) {
for (let j = 0; j < temp.length; j++) {
res.push(choice[i] + temp[j]);
}
}
return res;
}
}
var tempRes = generate(2 * n);
var result = [];
for (let i = 0; i < tempRes.length; i++) {
var mark = 0;
for (let j = 0; j < tempRes[i].length; j++) {
if (tempRes[i][j] === "(") {
mark++;
} else {
if (mark) mark--;
else {
mark--;
break;
}
}
}
if (mark === 0) result.push(tempRes[i]);
}
return result;
};