Generate Parentheses medium
Problem Statement
Given n
pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
Example 1
Input: n = 3 Output: ["((()))","(()())","(())()","()(())","()()()"]
Example 2
Input: n = 1 Output: ["()"]
Steps
The core idea is to use backtracking. We'll recursively explore all possible placements of opening and closing parentheses, keeping track of the balance using two variables:
open
: Counts the number of opening parentheses used so far.close
: Counts the number of closing parentheses used so far.
At each step, we have three possibilities:
- Add an opening parenthesis (
(
): Ifopen < n
(we haven't used all opening parentheses), we add an opening parenthesis, incrementopen
, and recursively call the function. - Add a closing parenthesis (
)
): Ifclose < open
(we have more opening parentheses than closing parentheses), we add a closing parenthesis, incrementclose
, and recursively call the function. - Base Case: If
open == n && close == n
(we've used all parentheses), we've found a valid combination, so we add it to the result.
Explanation
The backtracking approach systematically explores all valid combinations. The constraints open < n
and close < open
ensure that we only generate well-formed parentheses. The open < n
condition prevents adding more opening parentheses than allowed, while close < open
prevents adding a closing parenthesis before its matching opening parenthesis, thus avoiding invalid combinations like )(
.
Code
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> result;
backtrack(result, "", n, 0, 0);
return result;
}
private:
void backtrack(vector<string>& result, string current, int n, int open, int close) {
if (open == n && close == n) {
result.push_back(current);
return;
}
if (open < n) {
backtrack(result, current + "(", n, open + 1, close);
}
if (close < open) {
backtrack(result, current + ")", n, open, close + 1);
}
}
};
Complexity
- Time Complexity: O(4n / n1.5). This is a Catalan number, representing the number of valid combinations. While the naive approach would explore a much larger space, the constraints prune many invalid paths.
- Space Complexity: O(4n / n1.5) in the worst case, due to storing all generated parentheses combinations. The recursion depth is also O(n).