Balanced expressions such that given positions have opening brackets | Set 2
Last Updated :
13 Apr, 2023
Given an integer n and an array of positions ‘position[]’ (1 <= length(position[]) <= 2n), find the number of ways of proper bracket expressions that can be formed of length 2n such that given positions have the opening bracket.
Note: position[] array is given in the form of (1-based indexing) [0, 1, 1, 0]. Here 1 denotes the positions at which open bracket should be placed. At positions with value 0, either of opening and closing bracket can be placed.
Examples:
Input: n = 3, position[] = [0, 1, 0, 0, 0, 0]
Output: 3
The proper bracket sequences of length 6 and
opening bracket at position 2 are:
[ [ ] ] [ ]
[ [ [ ] ] ]
[ [ ] [ ] ]
Input: n = 2, position[] = [1, 0, 1, 0]
Output: 1
The only possibility is:
[ ] [ ]
Dynamic Programming approach of this problem has been already discussed here. In this post, recursive and recursion using memoization approach will be discussed.
Algorithm–
- Mark all the positions with open brackets in the given array adj as 1.
- Run a recursive loop, such that –
- If count of total brackets(opening brackets subtracted from closing brackets is less than zero), return 0.
- If the index reaches till n and if the total brackets=0, then a solution is obtained and return 1, otherwise return 0.
- If the index has 1 pre-assigned to it, return the function recursively with index+1 and increment the total brackets.
- Otherwise Return the function recursively by inserting open brackets at that index and incrementing total brackets by 1 + inserting closed brackets at that index and decrementing total brackets by 1 and move on to the next index till n.
Below is the Recursive solution for above algorithm:
C++
#include <bits/stdc++.h>
using namespace std;
int find( int index, int openbrk, int n, int adj[])
{
if (openbrk < 0)
return 0;
if (index == n) {
if (openbrk == 0)
return 1;
else
return 0;
}
if (adj[index] == 1) {
return find(index + 1, openbrk + 1, n, adj);
}
else {
return find(index + 1, openbrk + 1, n, adj)
+ find(index + 1, openbrk - 1, n, adj);
}
}
int main()
{
int n = 2;
int adj[4] = { 1, 0, 0, 0 };
cout << find(0, 0, 2 * n, adj) << endl;
return 0;
}
|
Java
class Test {
static int find( int index, int openbrk,
int n, int [] adj) {
if (openbrk < 0 ) {
return 0 ;
}
if (index == n) {
if (openbrk == 0 ) {
return 1 ;
} else {
return 0 ;
}
}
if (adj[index] == 1 ) {
return find(index + 1 , openbrk + 1 , n, adj);
} else {
return find(index + 1 , openbrk + 1 , n, adj)
+ find(index + 1 , openbrk - 1 , n, adj);
}
}
public static void main(String[] args) {
int n = 2 ;
int [] adj = { 1 , 0 , 0 , 0 };
System.out.print(find( 0 , 0 , 2 * n, adj));
}
}
|
Python3
N = 1000
def find(index, openbrk, n, dp, adj):
if (openbrk < 0 ):
return 0
if (index = = n):
if (openbrk = = 0 ):
return 1
else :
return 0
if (dp[index][openbrk] ! = - 1 ):
return dp[index][openbrk]
if (adj[index] = = 1 ):
dp[index][openbrk] = find(index + 1 ,
openbrk + 1 , n, dp, adj)
else :
dp[index][openbrk] = (find(index + 1 , openbrk + 1 ,
n, dp, adj) +
find(index + 1 , openbrk - 1 ,
n, dp, adj))
return dp[index][openbrk]
dp = [[ - 1 for i in range (N)]
for i in range (N)]
n = 2 ;
adj = [ 1 , 0 , 0 , 0 ]
print (find( 0 , 0 , 2 * n, dp, adj))
|
C#
using System;
class GFG
{
static int find( int index, int openbrk,
int n, int [] adj)
{
if (openbrk < 0)
return 0;
if (index == n)
{
if (openbrk == 0)
return 1;
else
return 0;
}
if (adj[index] == 1)
{
return find(index + 1, openbrk + 1, n, adj);
}
else
{
return find(index + 1, openbrk + 1, n, adj)
+ find(index + 1, openbrk - 1, n, adj);
}
}
public static void Main()
{
int n = 2;
int [] adj = { 1, 0, 0, 0 };
Console.WriteLine(find(0, 0, 2 * n, adj));
}
}
|
PHP
<?php
function find( $index , $openbrk , $n , & $adj )
{
if ( $openbrk < 0)
return 0;
if ( $index == $n )
{
if ( $openbrk == 0)
return 1;
else
return 0;
}
if ( $adj [ $index ] == 1)
{
return find( $index + 1,
$openbrk + 1, $n , $adj );
}
else
{
return find( $index + 1,
$openbrk + 1, $n , $adj ) +
find( $index + 1,
$openbrk - 1, $n , $adj );
}
}
$n = 2;
$adj = array (1, 0, 0, 0);
echo find(0, 0, 2 * $n , $adj ) . "\n" ;
?>
|
Javascript
<script>
function find(index, openbrk, n, adj)
{
if (openbrk < 0)
{
return 0;
}
if (index == n)
{
if (openbrk == 0)
{
return 1;
}
else
{
return 0;
}
}
if (adj[index] == 1)
{
return find(index + 1, openbrk + 1, n, adj);
}
else
{
return find(index + 1, openbrk + 1, n, adj) +
find(index + 1, openbrk - 1, n, adj);
}
}
let n = 2;
let adj = [ 1, 0, 0, 0 ];
document.write(find(0, 0, 2 * n, adj));
</script>
|
Time complexity O(2^n), where n is the total number of brackets in the expression.
Space complexity is O(n), which is the maximum number of recursive calls that can be stored on the call stack.
Memoized Approach: Time complexity of the above algorithm can be optimized by using Memorization. The only thing to be done is to use an array to store the results of previous iterations so that there is no need to recursively call the same function more than once if the value is already calculated.
Below is the required implementation:
C++
#include <bits/stdc++.h>
using namespace std;
#define N 1000
int find( int index, int openbrk, int n,
int dp[N][N], int adj[])
{
if (openbrk < 0)
return 0;
if (index == n) {
if (openbrk == 0)
return 1;
else
return 0;
}
if (dp[index][openbrk] != -1)
return dp[index][openbrk];
if (adj[index] == 1) {
dp[index][openbrk] = find(index + 1,
openbrk + 1, n, dp, adj);
}
else {
dp[index][openbrk] = find(index + 1, openbrk + 1, n, dp, adj)
+ find(index + 1, openbrk - 1, n, dp, adj);
}
return dp[index][openbrk];
}
int main()
{
int dp[N][N];
int n = 2;
memset (dp, -1, sizeof (dp));
int adj[4] = { 1, 0, 0, 0 };
cout << find(0, 0, 2 * n, dp, adj) << endl;
return 0;
}
|
Java
public class GFG {
static final int N = 1000 ;
static int find( int index, int openbrk, int n,
int dp[][], int adj[]) {
if (openbrk < 0 ) {
return 0 ;
}
if (index == n) {
if (openbrk == 0 ) {
return 1 ;
} else {
return 0 ;
}
}
if (dp[index][openbrk] != - 1 ) {
return dp[index][openbrk];
}
if (adj[index] == 1 ) {
dp[index][openbrk] = find(index + 1 ,
openbrk + 1 , n, dp, adj);
} else {
dp[index][openbrk] = find(index + 1 , openbrk + 1 , n, dp, adj)
+ find(index + 1 , openbrk - 1 , n, dp, adj);
}
return dp[index][openbrk];
}
public static void main(String[] args) {
int dp[][] = new int [N][N];
int n = 2 ;
for ( int i = 0 ; i < N; i++) {
for ( int j = 0 ; j < N; j++) {
dp[i][j] = - 1 ;
}
}
int adj[] = { 1 , 0 , 0 , 0 };
System.out.print(find( 0 , 0 , 2 * n, dp, adj));
}
}
|
Python3
N = 1000 ;
dp = [[ - 1 for x in range (N)]
for y in range (N)];
adj = [ 1 , 0 , 0 , 0 ];
def find(index, openbrk, n):
if (openbrk < 0 ):
return 0 ;
if (index = = n):
if (openbrk = = 0 ):
return 1 ;
else :
return 0 ;
if (dp[index][openbrk] ! = - 1 ):
return dp[index][openbrk];
if (adj[index] = = 1 ):
dp[index][openbrk] = find(index + 1 ,
openbrk + 1 , n);
else :
dp[index][openbrk] = (find(index + 1 , openbrk + 1 , n) +
find(index + 1 , openbrk - 1 , n));
return dp[index][openbrk];
n = 2 ;
print (find( 0 , 0 , 2 * n));
|
C#
using System;
class GFG
{
static readonly int N = 1000;
static int find( int index, int openbrk, int n,
int [,]dp, int []adj)
{
if (openbrk < 0)
{
return 0;
}
if (index == n)
{
if (openbrk == 0)
{
return 1;
}
else
{
return 0;
}
}
if (dp[index,openbrk] != -1)
{
return dp[index, openbrk];
}
if (adj[index] == 1)
{
dp[index, openbrk] = find(index + 1,
openbrk + 1, n, dp, adj);
}
else
{
dp[index, openbrk] = find(index + 1, openbrk + 1, n, dp, adj)
+ find(index + 1, openbrk - 1, n, dp, adj);
}
return dp[index,openbrk];
}
public static void Main()
{
int [,]dp = new int [N,N];
int n = 2;
for ( int i = 0; i < N; i++)
{
for ( int j = 0; j < N; j++)
{
dp[i, j] = -1;
}
}
int []adj = {1, 0, 0, 0};
Console.WriteLine(find(0, 0, 2 * n, dp, adj));
}
}
|
PHP
<?php
function find( $index , $openbrk , $n ,
& $dp , & $adj )
{
if ( $openbrk < 0)
return 0;
if ( $index == $n )
{
if ( $openbrk == 0)
return 1;
else
return 0;
}
if ( $dp [ $index ][ $openbrk ] != -1)
return $dp [ $index ][ $openbrk ];
if ( $adj [ $index ] == 1)
{
$dp [ $index ][ $openbrk ] = find( $index + 1,
$openbrk + 1, $n ,
$dp , $adj );
}
else
{
$dp [ $index ][ $openbrk ] = find( $index + 1, $openbrk + 1,
$n , $dp , $adj ) +
find( $index + 1, $openbrk - 1,
$n , $dp , $adj );
}
return $dp [ $index ][ $openbrk ];
}
$N = 1000;
$dp = array ( array ());
$n = 2;
for ( $i = 0; $i < $N ; $i ++)
{
for ( $j = 0; $j < $N ; $j ++)
{
$dp [ $i ][ $j ] = -1;
}
}
$adj = array ( 1, 0, 0, 0 );
echo find(0, 0, 2 * $n , $dp , $adj ) . "\n" ;
?>
|
Javascript
<script>
let N = 1000;
function find(index, openbrk, n, dp, adj)
{
if (openbrk < 0)
{
return 0;
}
if (index == n)
{
if (openbrk == 0)
{
return 1;
}
else
{
return 0;
}
}
if (dp[index][openbrk] != -1)
{
return dp[index][openbrk];
}
if (adj[index] == 1)
{
dp[index][openbrk] = find(index + 1,
openbrk + 1, n, dp, adj);
}
else
{
dp[index][openbrk] = find(index + 1, openbrk + 1,
n, dp, adj) +
find(index + 1, openbrk - 1,
n, dp, adj);
}
return dp[index][openbrk];
}
let dp = new Array(N);
for (let i = 0; i < N; i++)
{
dp[i] = new Array(N);
for (let j = 0; j < N; j++)
{
dp[i][j] = -1;
}
}
let n = 2;
let adj = [ 1, 0, 0, 0 ];
document.write(find(0, 0, 2 * n, dp, adj));
</script>
|
Time complexity: O(N2),because we are storing the intermediate results in a 2D array of size NN and we need to compute the value for each cell only once.
Space complexity:O(N2), because we are storing the intermediate results in a 2D array of size N*N.
Share your thoughts in the comments
Please Login to comment...