Problem Statement
Given an integer n, generate all combinations of well-formed parentheses that consist of exactly n pairs of opening and closing parentheses. The formed length would be 2*n.
LeetCode
https://leetcode.com/problems/generate-parentheses/description/
Constraints
1 <= n <= 8- The constraint
1 <= n <= 8typically indicates that:nis small โ it's a number between 1 and 8.- You can use algorithms with high time complexity, such as brute-force, backtracking, or recursion with permutations, because the total number of possibilities will be small.
Examples
Example 1:
Input: n = 3
Output:[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]Example 2:
Input: n = 2
Output: [
"(())",
"()()"
]Example 3:
Input: n = 1
Output: [
"()"
]Constraints for Well-Formed Parentheses:
To be considered a well-formed (valid) parentheses combination:
- The number of opening parentheses
'('should always be equal to the number of closing parentheses')'. - At any point in the combination, the number of closing parentheses
')'should not exceed the number of opening parentheses'('. If it does, the combination is invalid.
Different Approaches
1๏ธโฃ Recursion
The idea is to build the parentheses string recursively, ensuring that at any point:
- We can add an opening parenthesis
(if we havenโt used allnopening parentheses yet. - We can add a closing parenthesis
)only if the number of closing parentheses is less than the number of opening parentheses used so far.
The recursive approach is a classic depth-first search (DFS) where we try to build valid parentheses strings by adding an open ( or a close ) at each step, ensuring that:
- We can only add an open
(if we have fewer thannopen parentheses. - We can only add a close
)if the number of close parentheses is less than the number of open parentheses.
Recursive Algorithm:
- Start with an empty string and
nas the input for the number of pairs of parentheses. - At each step, you have two options:
- Add an open
(parenthesis if you havenโt used allnopen parentheses. - Add a close
)parenthesis if the number of close parentheses is less than the number of open parentheses.
- Add an open
- When the string reaches a length of
2 * n(which means all open and close parentheses have been used), add it to the result.
Recursion Tree:


Code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void generateParenthesisRec(int open, int close, string current, vector<string>& result) {
// Base case: If the current string is valid and complete
if (open == 0 && close == 0) {
result.push_back(current);
return;
}
// Recursive case: Try to add open and close parentheses
if (open > 0) {
generateParenthesisRec(open - 1, close, current + "(", result);
}
if (close > open) {
generateParenthesisRec(open, close - 1, current + ")", result);
}
}
vector<string> generateParenthesis(int n) {
vector<string> result;
generateParenthesisRec(n, n, "", result);
return result;
}
int main() {
int n = 3;
vector<string> result = generateParenthesis(n);
for (const string &s : result) {
cout << s << endl;
}
return 0;
}
Visualization of the Recursive Process for n = 3:
We start with n = 3 pairs of parentheses. At each step, we can either add an open parenthesis ( if open > 0 or a close parenthesis ) if close > open.
Hereโs a recursive tree that illustrates the process:
""
/ \
"(" ""
/ \ \
"((" "()" ""
/ \ / \ \
"(((" "(()" "()(" "()" ""
/ \ / \ / \ \ \
"((())" "(()()" "()()" "()" "()(" ""
| | | | | |
"((()))" "(()())" "(())()" "()(())" "()()()"
Detailed Walkthrough:
At each node in the recursion tree:
- Open parentheses (
() are added if there are still open parentheses left. - Close parentheses (
)) are added if the number of close parentheses is less than the number of open parentheses.
Step-by-Step Breakdown:
- Start with the empty string
"":- Add an open parenthesis
(. - Now you have
open = 2andclose = 3.
- Add an open parenthesis
- At
"(":- You still have
open = 2andclose = 3remaining. - Add another open parenthesis
(โ"((". - Now you have
open = 1andclose = 3.
- You still have
- At
"((":- Add another open parenthesis
(โ"(((". - Now you have
open = 0andclose = 3.
- Add another open parenthesis
- At
"(((":- No more open parentheses to add (
open = 0). - Add a close parenthesis
)โ"((()". - Now you have
open = 0andclose = 2.
- No more open parentheses to add (
- At
"((()":- Add another close parenthesis
)โ"((())". - Now you have
open = 0andclose = 1.
- Add another close parenthesis
- At
"((())":- Add another close parenthesis
)โ"((()))". - Now you have
open = 0andclose = 0. - Since both
openandcloseare 0, the string"((()))"is a valid solution.
- Add another close parenthesis
- Backtracking:
- Backtrack to previous nodes and try other combinations, like adding close parentheses earlier:
"(()()","()(())","()()()", etc.
- Backtrack to previous nodes and try other combinations, like adding close parentheses earlier:
Complexity Analysis:
- Time Complexity:
- The time complexity is proportional to the
Catalan numberCn, which is approximatelyO(4^n / under-root of n).
- The time complexity is proportional to the
- Space Complexity:
- The space complexity is
O(n)for the recursion stack since each recursive call adds one level to the stack (up tonlevels deep). - The result takes up
O(4^n / under-root of n)space to store all valid combinations.
- The space complexity is
