...

/

Generate all Combinations of Balanced Parentheses

Generate all Combinations of Balanced Parentheses

Generate all combinations of balanced parentheses for the n number of parentheses pairs.

Statement

Write a function to generate all balanced combinations of nn pairs of parentheses.

Example

Here are a few examples:

foo a1 N: 1 {} a2 N: 2 {{}} {}{} a3 N: 3 {{{}}} {}{{}} {{}{}} {{}}{} {}{}{}

The test cases will use values of nn in the range of 1 to 6.

Sample input

3

Expected output

{{{}}}
{{}{}}
{{}}{}
{}{{}}
{}{}{}

Try it yourself

#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector <string> GenerateCombinations(int n) {
vector <string> result;
// TODO: Write - Your - Code
return result;
}

Solution

The solution is to keep track of the number of opening and closing parentheses. We’ll use this count to add parentheses in a way that keeps the sequence valid.

  • We only add an opening parenthesis if there is still one to add.
  • We only add a closing parenthesis if its count does not exceed the number of opening parentheses.

The basic algorithm is as follows:​

open_braces count: 0
close_braces count: 0

if open_braces count is less than n:
    add open_braces and recurse further
if close_braces count is less than open_braces count:
    add close_braces and recurse further

stop recursing when open_braces and close_braces counts are both equal to n

Let’s go through an example n=3n = 3, to understand the solution. The output is shown at the leaf level.

Now let’s look at the code in our favorite language below:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
// The recursive backtracking function
void Backtrack(
int n, // The input n
int open_braces_count, // Count of the opening braces
int close_braces_count, // Count of the closing braces
vector <char> & output, // Stores the recursive output
vector <string> & result) {
// Base case where count of opening and closing braces is n
if (open_braces_count >= n && close_braces_count >= n) {
string temp = string(output.begin(), output.end());
result.push_back(temp);
}
// Case where we can still add opening braces
if (open_braces_count < n) {
output.push_back('{');
Backtrack(n, open_braces_count + 1, close_braces_count, output, result);
output.pop_back();
}
// Case where we add closing braces if the current count
// of closing braces is less than the count of opening braces
if (close_braces_count < open_braces_count) {
output.push_back('}');
Backtrack(n, open_braces_count, close_braces_count + 1, output, result);
output.pop_back();
}
}
vector <string> GenerateCombinations(int n) {
vector <string> result;
vector <char> output;
Backtrack(n, 0, 0, output, result);
return result;
}
int main() {
vector <string> result;
int n[] = {1, 2, 3, 4};
for (int i = 0; i < 4; i++) {
cout<< i+1<<". n = "<<n[i]<<endl;
cout<<" Combinations of all balanced parentheses:"<<endl;
result = GenerateCombinations(n[i]);
for (int j = 0; j < result.size(); j++) {
cout << " " <<result[j] << endl;
}
cout<<"----------------------------------------------------------------------------------------"<<endl;
}
}

Time complexity

As visualized in the slides above, it is easier to understand the problem by creating a tree. Given a tree with branching of b ...