给定一个字符串“ S”,该字符串由方括号和右括号组成,可以找到将“ S”的每个字符分配给字符串“ X”或字符串“ Y”(最初均为空)的方式,例如X和Y组成的字符串是平衡的。可以假设“ S”本身是平衡的。
例子:
Input: S = "(())"
Output: 6
Valid assignments are :
X = "(())" and Y = "" [All characters in X]
X = "" and Y = "(())" [Nothing in X]
X = "()" and Y = "()" [1st and 3rd characters in X]
X = "()" and Y = "()" [2nd and 3rd characters in X]
X = "()" and Y = "()" [2nd and 4th characters in X]
X = "()" and Y = "()" [1st and 4th characters in X]
Input: S = "()()"
Output: 4
X = "()()", Y = ""
X = "()", Y = "()" [1st and 2nd in X]
X = "()", Y = "" [1st and 4th in X]
X = "", Y = "()()"
一种简单的方法:我们可以生成分配字符的所有可能方式,并检查形成的字符串是否平衡。有2 n个分配,有效或无效,并且需要O(n)时间来检查所形成的字符串是否平衡。因此,该方法的时间复杂度为O(n * 2 n )。
一种有效的方法(动态编程):我们可以使用动态编程以更有效的方式解决此问题。我们可以使用三个变量来描述当前的赋值状态:要赋值的字符的索引i,以及由X和Y形成的字符串。将整个字符串传递给函数调用将导致较高的内存需求,因此我们可以将它们替换为计数变量c x和c y 。我们将为每个左括号增加count变量,并为每个右括号减少count变量。该方法的时间和空间复杂度为O(n 3 )。
下面是上述方法的实现:
C++
// C++ implementation of
// the above approach
#include
using namespace std;
// For maximum length of input string
const int MAX = 10;
// Declaring the DP table
int F[MAX][MAX][MAX];
// Function to calculate the
// number of valid assignments
int noOfAssignments(string& S, int& n, int i,
int c_x, int c_y)
{
if (F[i][c_x][c_y] != -1)
return F[i][c_x][c_y];
if (i == n) {
// Return 1 if both
// subsequences are balanced
F[i][c_x][c_y] = !c_x && !c_y;
return F[i][c_x][c_y];
}
// Increment the count
// if it an opening bracket
if (S[i] == '(') {
F[i][c_x][c_y]
= noOfAssignments(S, n, i + 1,
c_x + 1, c_y)
+ noOfAssignments(S, n, i + 1,
c_x, c_y + 1);
return F[i][c_x][c_y];
}
F[i][c_x][c_y] = 0;
// Decrement the count
// if it a closing bracket
if (c_x)
F[i][c_x][c_y]
+= noOfAssignments(S, n, i + 1,
c_x - 1, c_y);
if (c_y)
F[i][c_x][c_y]
+= noOfAssignments(S, n, i + 1,
c_x, c_y - 1);
return F[i][c_x][c_y];
}
// Driver code
int main()
{
string S = "(())";
int n = S.length();
// Initializing the DP table
memset(F, -1, sizeof(F));
// Intitial value for c_x
// and c_y is zero
cout << noOfAssignments(S, n, 0, 0, 0);
return 0;
}
Java
// Java implementation of the above approach
class GFG
{
// For maximum length of input string
static int MAX = 10;
// Declaring the DP table
static int[][][] F = new int[MAX][MAX][MAX];
// Function to calculate the
// number of valid assignments
static int noOfAssignments(String s, int n,
int i, int c_x, int c_y)
{
if (F[i][c_x][c_y] != -1)
return F[i][c_x][c_y];
if (i == n)
{
// Return 1 if both
// subsequences are balanced
F[i][c_x][c_y] = (c_x == 0 &&
c_y == 0) ? 1 : 0;
return F[i][c_x][c_y];
}
// Increment the count
// if it an opening bracket
if (s.charAt(i) == '(')
{
F[i][c_x][c_y] = noOfAssignments(s, n, i + 1,
c_x + 1, c_y) +
noOfAssignments(s, n, i + 1,
c_x, c_y + 1);
return F[i][c_x][c_y];
}
F[i][c_x][c_y] = 0;
// Decrement the count
// if it a closing bracket
if (c_x != 0)
F[i][c_x][c_y] += noOfAssignments(s, n, i + 1,
c_x - 1, c_y);
if (c_y != 0)
F[i][c_x][c_y] += noOfAssignments(s, n, i + 1,
c_x, c_y - 1);
return F[i][c_x][c_y];
}
// Driver Code
public static void main(String[] args)
{
String s = "(())";
int n = s.length();
// Initializing the DP table
for (int i = 0; i < MAX; i++)
for (int j = 0; j < MAX; j++)
for (int k = 0; k < MAX; k++)
F[i][j][k] = -1;
// Intitial value for c_x
// and c_y is zero
System.out.println(noOfAssignments(s, n, 0, 0, 0));
}
}
// This code is contributed by
// sanjeev2552
Python3
# Python3 implementation of above approach
# For maximum length of input string
MAX = 10
# Declaring the DP table
F = [[[-1 for i in range(MAX)]
for j in range(MAX)]
for k in range(MAX)]
# Function to calculate the number
# of valid assignments
def noOfAssignments(S, n, i, c_x, c_y):
if F[i][c_x][c_y] != -1:
return F[i][c_x][c_y]
if i == n:
# Return 1 if both subsequences are balanced
F[i][c_x][c_y] = not c_x and not c_y
return F[i][c_x][c_y]
# Increment the count if
# it is an opening bracket
if S[i] == '(':
F[i][c_x][c_y] = \
noOfAssignments(S, n, i + 1, c_x + 1, c_y) + \
noOfAssignments(S, n, i + 1, c_x, c_y + 1)
return F[i][c_x][c_y]
F[i][c_x][c_y] = 0
# Decrement the count
# if it a closing bracket
if c_x:
F[i][c_x][c_y] += \
noOfAssignments(S, n, i + 1, c_x - 1, c_y)
if c_y:
F[i][c_x][c_y] += \
noOfAssignments(S, n, i + 1, c_x, c_y - 1)
return F[i][c_x][c_y]
# Driver code
if __name__ == "__main__":
S = "(())"
n = len(S)
# Intitial value for c_x and c_y is zero
print(noOfAssignments(S, n, 0, 0, 0))
# This code is contributed by Rituraj Jain
C#
// C# implementation of the above approach
using System;
class GFG
{
// For maximum length of input string
static int MAX = 10;
// Declaring the DP table
static int[,,] F = new int[MAX, MAX, MAX];
// Function to calculate the
// number of valid assignments
static int noOfAssignments(String s, int n,
int i, int c_x, int c_y)
{
if (F[i, c_x, c_y] != -1)
return F[i, c_x, c_y];
if (i == n)
{
// Return 1 if both
// subsequences are balanced
F[i, c_x, c_y] = (c_x == 0 &&
c_y == 0) ? 1 : 0;
return F[i, c_x, c_y];
}
// Increment the count
// if it an opening bracket
if (s[i] == '(')
{
F[i, c_x, c_y] = noOfAssignments(s, n, i + 1,
c_x + 1, c_y) +
noOfAssignments(s, n, i + 1,
c_x, c_y + 1);
return F[i, c_x, c_y];
}
F[i, c_x, c_y] = 0;
// Decrement the count
// if it a closing bracket
if (c_x != 0)
F[i, c_x, c_y] += noOfAssignments(s, n, i + 1,
c_x - 1, c_y);
if (c_y != 0)
F[i, c_x, c_y] += noOfAssignments(s, n, i + 1,
c_x, c_y - 1);
return F[i, c_x, c_y];
}
// Driver Code
public static void Main(String[] args)
{
String s = "(())";
int n = s.Length;
// Initializing the DP table
for (int i = 0; i < MAX; i++)
for (int j = 0; j < MAX; j++)
for (int k = 0; k < MAX; k++)
F[i, j, k] = -1;
// Intitial value for c_x
// and c_y is zero
Console.WriteLine(noOfAssignments(s, n, 0, 0, 0));
}
}
// This code is contributed by PrinciRaj1992
C++
// C++ implementation of
// the above approach
#include
using namespace std;
// For maximum length of input string
const int MAX = 10;
// Declaring the DP table
int F[MAX][MAX];
// Declaring the prefix array
int C[MAX];
// Function to calculate the
// number of valid assignments
int noOfAssignments(string& S, int& n,
int i, int c_x)
{
if (F[i][c_x] != -1)
return F[i][c_x];
if (i == n) {
// Return 1 if X is
// balanced.
F[i][c_x] = !c_x;
return F[i][c_x];
}
int c_y = C[i] - c_x;
// Increment the count
// if it an opening bracket
if (S[i] == '(') {
F[i][c_x]
= noOfAssignments(S, n, i + 1,
c_x + 1)
+ noOfAssignments(S, n,
i + 1, c_x);
return F[i][c_x];
}
F[i][c_x] = 0;
// Decrement the count
// if it a closing bracket
if (c_x)
F[i][c_x]
+= noOfAssignments(S, n,
i + 1, c_x - 1);
if (c_y)
F[i][c_x]
+= noOfAssignments(S, n,
i + 1, c_x);
return F[i][c_x];
}
// Driver code
int main()
{
string S = "()";
int n = S.length();
// Initializing the DP table
memset(F, -1, sizeof(F));
C[0] = 0;
// Creating the prefix array
for (int i = 0; i < n; ++i)
if (S[i] == '(')
C[i + 1] = C[i] + 1;
else
C[i + 1] = C[i] - 1;
// Initial value for c_x
// and c_y is zero
cout << noOfAssignments(S, n, 0, 0);
return 0;
}
Java
// Java implementation of the approach
public class GFG {
// For maximum length of input string
static int MAX = 10;
// Declaring the DP table
static int F[][] = new int[MAX][MAX];
// Declaring the prefix array
static int C[] = new int[MAX];
// Function to calculate the
// number of valid assignments
static int noOfAssignments(String S, int n, int i, int c_x) {
if (F[i][c_x] != -1) {
return F[i][c_x];
}
if (i == n) {
// Return 1 if X is
// balanced.
if (c_x == 1) {
F[i][c_x] = 0;
} else {
F[i][c_x] = 1;
}
return F[i][c_x];
}
int c_y = C[i] - c_x;
// Increment the count
// if it an opening bracket
if (S.charAt(i) == '(') {
F[i][c_x]
= noOfAssignments(S, n, i + 1,
c_x + 1)
+ noOfAssignments(S, n,
i + 1, c_x);
return F[i][c_x];
}
F[i][c_x] = 0;
// Decrement the count
// if it a closing bracket
if (c_x == 1) {
F[i][c_x]
+= noOfAssignments(S, n,
i + 1, c_x - 1);
}
if (c_y == 1) {
F[i][c_x]
+= noOfAssignments(S, n,
i + 1, c_x);
}
return F[i][c_x];
}
// Driver code
public static void main(String[] args) {
String S = "()";
int n = S.length();
// Initializing the DP table
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
F[i][j] = -1;
}
}
C[0] = 0;
// Creating the prefix array
for (int i = 0; i < n; ++i) {
if (S.charAt(i) == '(') {
C[i + 1] = C[i] + 1;
} else {
C[i + 1] = C[i] - 1;
}
}
// Initial value for c_x
// and c_y is zero
System.out.println(noOfAssignments(S, n, 0, 0));
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 implementation of above approach
# For maximum length of input string
MAX = 10
# Declaring the DP table
F = [[-1 for i in range(MAX)]
for j in range(MAX)]
# Declaring the prefix array
C = [None] * MAX
# Function to calculate the
# number of valid assignments
def noOfAssignments(S, n, i, c_x):
if F[i][c_x] != -1:
return F[i][c_x]
if i == n:
# Return 1 if X is balanced.
F[i][c_x] = not c_x
return F[i][c_x]
c_y = C[i] - c_x
# Increment the count
# if it is an opening bracket
if S[i] == '(':
F[i][c_x] = \
noOfAssignments(S, n, i + 1, c_x + 1) + \
noOfAssignments(S, n, i + 1, c_x)
return F[i][c_x]
F[i][c_x] = 0
# Decrement the count if it is a closing bracket
if c_x:
F[i][c_x] += \
noOfAssignments(S, n, i + 1, c_x - 1)
if c_y:
F[i][c_x] += \
noOfAssignments(S, n, i + 1, c_x)
return F[i][c_x]
# Driver code
if __name__ == "__main__":
S = "()"
n = len(S)
C[0] = 0
# Creating the prefix array
for i in range(0, n):
if S[i] == '(':
C[i + 1] = C[i] + 1
else:
C[i + 1] = C[i] - 1
# Initial value for c_x and c_y is zero
print(noOfAssignments(S, n, 0, 0))
# This code is contributed by Rituraj Jain
C#
// C# implementation of the approach
using System;
public class GFG {
// For maximum length of input string
static int MAX = 10;
// Declaring the DP table
static int[,] F = new int[MAX,MAX];
// Declaring the prefix array
static int[] C = new int[MAX];
// Function to calculate the
// number of valid assignments
static int noOfAssignments(string S, int n, int i, int c_x) {
if (F[i,c_x] != -1) {
return F[i,c_x];
}
if (i == n) {
// Return 1 if X is
// balanced.
if (c_x == 1) {
F[i,c_x] = 0;
} else {
F[i,c_x] = 1;
}
return F[i,c_x];
}
int c_y = C[i] - c_x;
// Increment the count
// if it an opening bracket
if (S[i] == '(') {
F[i,c_x]
= noOfAssignments(S, n, i + 1,
c_x + 1)
+ noOfAssignments(S, n,
i + 1, c_x);
return F[i,c_x];
}
F[i,c_x] = 0;
// Decrement the count
// if it a closing bracket
if (c_x == 1) {
F[i,c_x]
+= noOfAssignments(S, n,
i + 1, c_x - 1);
}
if (c_y == 1) {
F[i,c_x]
+= noOfAssignments(S, n,
i + 1, c_x);
}
return F[i,c_x];
}
// Driver code
public static void Main() {
string S = "()";
int n = S.Length;
// Initializing the DP table
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
F[i,j] = -1;
}
}
C[0] = 0;
// Creating the prefix array
for (int i = 0; i < n; ++i) {
if (S[i] == '(') {
C[i + 1] = C[i] + 1;
} else {
C[i + 1] = C[i] - 1;
}
}
// Initial value for c_x
// and c_y is zero
Console.WriteLine(noOfAssignments(S, n, 0, 0));
}
}
// This code is contributed by Ita_c.
输出:
6
优化的动态编程方法:我们可以创建一个前缀数组来存储子字符串S [0:i + 1]的计数变量c i 。我们可以观察到c_x和c_y的总和始终等于整个字符串的count变量。通过利用此属性,我们可以将动态编程方法简化为两种状态。可以以线性复杂度创建前缀数组,因此此方法的时间和空间复杂度为O(n 2 )。
C++
// C++ implementation of
// the above approach
#include
using namespace std;
// For maximum length of input string
const int MAX = 10;
// Declaring the DP table
int F[MAX][MAX];
// Declaring the prefix array
int C[MAX];
// Function to calculate the
// number of valid assignments
int noOfAssignments(string& S, int& n,
int i, int c_x)
{
if (F[i][c_x] != -1)
return F[i][c_x];
if (i == n) {
// Return 1 if X is
// balanced.
F[i][c_x] = !c_x;
return F[i][c_x];
}
int c_y = C[i] - c_x;
// Increment the count
// if it an opening bracket
if (S[i] == '(') {
F[i][c_x]
= noOfAssignments(S, n, i + 1,
c_x + 1)
+ noOfAssignments(S, n,
i + 1, c_x);
return F[i][c_x];
}
F[i][c_x] = 0;
// Decrement the count
// if it a closing bracket
if (c_x)
F[i][c_x]
+= noOfAssignments(S, n,
i + 1, c_x - 1);
if (c_y)
F[i][c_x]
+= noOfAssignments(S, n,
i + 1, c_x);
return F[i][c_x];
}
// Driver code
int main()
{
string S = "()";
int n = S.length();
// Initializing the DP table
memset(F, -1, sizeof(F));
C[0] = 0;
// Creating the prefix array
for (int i = 0; i < n; ++i)
if (S[i] == '(')
C[i + 1] = C[i] + 1;
else
C[i + 1] = C[i] - 1;
// Initial value for c_x
// and c_y is zero
cout << noOfAssignments(S, n, 0, 0);
return 0;
}
Java
// Java implementation of the approach
public class GFG {
// For maximum length of input string
static int MAX = 10;
// Declaring the DP table
static int F[][] = new int[MAX][MAX];
// Declaring the prefix array
static int C[] = new int[MAX];
// Function to calculate the
// number of valid assignments
static int noOfAssignments(String S, int n, int i, int c_x) {
if (F[i][c_x] != -1) {
return F[i][c_x];
}
if (i == n) {
// Return 1 if X is
// balanced.
if (c_x == 1) {
F[i][c_x] = 0;
} else {
F[i][c_x] = 1;
}
return F[i][c_x];
}
int c_y = C[i] - c_x;
// Increment the count
// if it an opening bracket
if (S.charAt(i) == '(') {
F[i][c_x]
= noOfAssignments(S, n, i + 1,
c_x + 1)
+ noOfAssignments(S, n,
i + 1, c_x);
return F[i][c_x];
}
F[i][c_x] = 0;
// Decrement the count
// if it a closing bracket
if (c_x == 1) {
F[i][c_x]
+= noOfAssignments(S, n,
i + 1, c_x - 1);
}
if (c_y == 1) {
F[i][c_x]
+= noOfAssignments(S, n,
i + 1, c_x);
}
return F[i][c_x];
}
// Driver code
public static void main(String[] args) {
String S = "()";
int n = S.length();
// Initializing the DP table
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
F[i][j] = -1;
}
}
C[0] = 0;
// Creating the prefix array
for (int i = 0; i < n; ++i) {
if (S.charAt(i) == '(') {
C[i + 1] = C[i] + 1;
} else {
C[i + 1] = C[i] - 1;
}
}
// Initial value for c_x
// and c_y is zero
System.out.println(noOfAssignments(S, n, 0, 0));
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 implementation of above approach
# For maximum length of input string
MAX = 10
# Declaring the DP table
F = [[-1 for i in range(MAX)]
for j in range(MAX)]
# Declaring the prefix array
C = [None] * MAX
# Function to calculate the
# number of valid assignments
def noOfAssignments(S, n, i, c_x):
if F[i][c_x] != -1:
return F[i][c_x]
if i == n:
# Return 1 if X is balanced.
F[i][c_x] = not c_x
return F[i][c_x]
c_y = C[i] - c_x
# Increment the count
# if it is an opening bracket
if S[i] == '(':
F[i][c_x] = \
noOfAssignments(S, n, i + 1, c_x + 1) + \
noOfAssignments(S, n, i + 1, c_x)
return F[i][c_x]
F[i][c_x] = 0
# Decrement the count if it is a closing bracket
if c_x:
F[i][c_x] += \
noOfAssignments(S, n, i + 1, c_x - 1)
if c_y:
F[i][c_x] += \
noOfAssignments(S, n, i + 1, c_x)
return F[i][c_x]
# Driver code
if __name__ == "__main__":
S = "()"
n = len(S)
C[0] = 0
# Creating the prefix array
for i in range(0, n):
if S[i] == '(':
C[i + 1] = C[i] + 1
else:
C[i + 1] = C[i] - 1
# Initial value for c_x and c_y is zero
print(noOfAssignments(S, n, 0, 0))
# This code is contributed by Rituraj Jain
C#
// C# implementation of the approach
using System;
public class GFG {
// For maximum length of input string
static int MAX = 10;
// Declaring the DP table
static int[,] F = new int[MAX,MAX];
// Declaring the prefix array
static int[] C = new int[MAX];
// Function to calculate the
// number of valid assignments
static int noOfAssignments(string S, int n, int i, int c_x) {
if (F[i,c_x] != -1) {
return F[i,c_x];
}
if (i == n) {
// Return 1 if X is
// balanced.
if (c_x == 1) {
F[i,c_x] = 0;
} else {
F[i,c_x] = 1;
}
return F[i,c_x];
}
int c_y = C[i] - c_x;
// Increment the count
// if it an opening bracket
if (S[i] == '(') {
F[i,c_x]
= noOfAssignments(S, n, i + 1,
c_x + 1)
+ noOfAssignments(S, n,
i + 1, c_x);
return F[i,c_x];
}
F[i,c_x] = 0;
// Decrement the count
// if it a closing bracket
if (c_x == 1) {
F[i,c_x]
+= noOfAssignments(S, n,
i + 1, c_x - 1);
}
if (c_y == 1) {
F[i,c_x]
+= noOfAssignments(S, n,
i + 1, c_x);
}
return F[i,c_x];
}
// Driver code
public static void Main() {
string S = "()";
int n = S.Length;
// Initializing the DP table
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
F[i,j] = -1;
}
}
C[0] = 0;
// Creating the prefix array
for (int i = 0; i < n; ++i) {
if (S[i] == '(') {
C[i + 1] = C[i] + 1;
} else {
C[i + 1] = C[i] - 1;
}
}
// Initial value for c_x
// and c_y is zero
Console.WriteLine(noOfAssignments(S, n, 0, 0));
}
}
// This code is contributed by Ita_c.
输出:
2