You are given an array of strings arr[], where each string contains only lowercase English letters. Count the number of contiguous subarrays (i.e., one or more consecutive strings from arr[]) whose concatenation forms a balanced string.
Note: A string is considered balanced if it contains an equal number of vowels and consonants.
Examples:
Input: arr[] = ["aeio", "aa", "bc", "ot", "cdbd"]
Output: 4
Explanation: arr[0...4], arr[1...2], arr[1...3], arr[3...3] are the balanced substrings with equal consonants and vowels.Input: arr[] = ["ab", "be"]
Output: 3
Explanation: arr[0..0], arr[0..1], arr[1..1] are the balanced substrings with equal consonants and vowels.Input: arr[] = ["tz", "gfg", "ae"]
Output: 0
Explanation: There is no such balanced substring present in arr[] with equal consonants and vowels.
[Naive Approach] Generate all possible subarrays
Try all possible contiguous subarrays of arr[], concatenate the strings within each subarray, and count the number of vowels and consonants in the resulting string. If the counts are equal, the string is considered balanced, and we increment our result.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// Helper to check if a character is a vowel
bool isVowel(char ch) {
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u';
}
// Function to count balanced subarrays
int countBalanced(vector<string>& arr) {
int n = arr.size();
int res = 0;
// Try all subarrays
for (int i = 0; i < n; i++) {
string s = "";
for (int j = i; j < n; j++) {
s += arr[j];
// vowel and consonant counts
int v = 0, c = 0;
// Count vowels and consonants
for (char ch : s) {
if (isVowel(ch)) v++;
else c++;
}
// If balanced, increase count
if (v == c) res++;
}
}
return res;
}
int main() {
vector<string> arr = {"aeio", "aa", "bc", "ot", "cdbd"};
cout << countBalanced(arr) << endl;
return 0;
}
public class GfG {
// Helper to check if a character is a vowel
public static boolean isVowel(char ch) {
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u';
}
// Function to count balanced subarrays
public static int countBalanced(String[] arr) {
int n = arr.length;
int res = 0;
for (int i = 0; i < n; i++) {
String s = "";
for (int j = i; j < n; j++) {
s += arr[j];
int v = 0, c = 0;
// Count vowels and consonants
for (char ch : s.toCharArray()) {
if (isVowel(ch)) v++;
else c++;
}
if (v == c) res++;
}
}
return res;
}
public static void main(String[] args) {
String[] arr = {"aeio", "aa", "bc", "ot", "cdbd"};
System.out.println(countBalanced(arr));
}
}
# Helper to check if a character is a vowel
def isVowel(ch):
return ch in 'aeiou'
# Function to count balanced subarrays
def countBalanced(arr):
n = len(arr)
res = 0
for i in range(n):
s = ''
for j in range(i, n):
s += arr[j]
v = c = 0
# Count vowels and consonants
for ch in s:
if isVowel(ch):
v += 1
else:
c += 1
if v == c:
res += 1
return res
if __name__ == "__main__":
arr = ["aeio", "aa", "bc", "ot", "cdbd"]
print(countBalanced(arr))
using System;
class GfG
{
// Helper to check if a character is a vowel
static bool isVowel(char ch) {
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u';
}
// Function to count balanced subarrays
static int countBalanced(string[] arr)
{
int n = arr.Length;
int res = 0;
for (int i = 0; i < n; i++)
{
string s = "";
for (int j = i; j < n; j++)
{
s += arr[j];
int v = 0, c = 0;
// Count vowels and consonants
foreach (char ch in s) {
if (isVowel(ch)) v++;
else c++;
}
if (v == c) res++;
}
}
return res;
}
static void Main()
{
string[] arr = { "aeio", "aa", "bc", "ot", "cdbd" };
Console.WriteLine(countBalanced(arr));
}
}
// Helper to check if a character is a vowel
function isVowel(ch) {
return 'aeiou'.includes(ch);
}
// Function to count balanced subarrays
function countBalanced(arr) {
let n = arr.length;
let res = 0;
for (let i = 0; i < n; i++) {
let s = "";
for (let j = i; j < n; j++) {
s += arr[j];
let v = 0, c = 0;
// Count vowels and consonants
for (let ch of s) {
if (isVowel(ch)) v++;
else c++;
}
if (v === c) res++;
}
}
return res;
}
// Driver Code
const arr = ["aeio", "aa", "bc", "ot", "cdbd"];
console.log(countBalanced(arr));
Output
4
Time Complexity: O(nÂē * l), where n is the number of strings and l is the total length of all strings combined, because for each of the O(nÂē) subarrays, all characters are concatenated and scanned.
Space Complexity: O(l), where l is the length of the longest possible concatenated string, used by the temporary string s.
[Expected Approach] Using Hash Map
Assign each string a net score: +1 for every vowel and -1 for every consonant. Compute the prefix sum of these scores across the array. If the same prefix sum appears more than once, the subarray between those indices has equal vowels and consonants. Use a hash map to count the frequency of each prefix sum during traversal. Add the frequency of the current prefix sum to the result before updating it.
#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
using namespace std;
// Function to check if a character is a vowel
bool isVowel(char ch) {
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u';
}
// Function to count the number of balanced subarrays
int countBalanced(vector<string>& arr) {
int n = arr.size();
int res = 0;
int prefix = 0;
// Map to store frequency of prefix sums
unordered_map<int, int> freq;
// Initial prefix sum is 0
//(empty prefix is considered balanced)
freq[0] = 1;
// Traverse the array of strings
for (int i = 0; i < n; i++) {
int score = 0;
// Calculate net score of current
// string: +1 for vowel, -1 for consonant
for (char ch : arr[i]) {
if (isVowel(ch)) score++;
else score--;
}
// Update the running prefix sum
prefix += score;
// If this prefix sum has been seen before,
// then the subarray between previous and
// current prefix is balanced
res += freq[prefix];
// Increment the frequency of this prefix sum
freq[prefix]++;
}
return res;
}
int main() {
vector<string> arr = {"aeio", "aa", "bc", "ot", "cdbd"};
cout << countBalanced(arr) << endl;
return 0;
}
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
public class GfG {
// Function to check if a character is a vowel
public static boolean isVowel(char ch) {
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u';
}
// Function to count the number of balanced subarrays
public static int countBalanced(String[] arr) {
int n = arr.length;
int res = 0;
int prefix = 0;
// Map to store frequency of prefix sums
Map<Integer, Integer> freq = new HashMap<>();
// Initial prefix sum is 0 (empty prefix is considered balanced)
freq.put(0, 1);
// Traverse the array of strings
for (int i = 0; i < n; i++) {
int score = 0;
// Calculate net score of current
// string: +1 for vowel, -1 for consonant
for (char ch : arr[i].toCharArray()) {
if (isVowel(ch)) score++;
else score--;
}
// Update the running prefix sum
prefix += score;
// If this prefix sum has been seen before,
// then the subarray between previous and
// current prefix is balanced
res += freq.getOrDefault(prefix, 0);
// Increment the frequency of this prefix sum
freq.put(prefix, freq.getOrDefault(prefix, 0) + 1);
}
return res;
}
public static void main(String[] args) {
String[] arr = {"aeio", "aa", "bc", "ot", "cdbd"};
System.out.println(countBalanced(arr));
}
}
from collections import defaultdict
# Function to check if a character is a vowel
def isVowel(ch):
return ch in 'aeiou'
# Function to count the number of balanced subarrays
def countBalanced(arr):
n = len(arr)
res = 0
prefix = 0
# Map to store frequency of prefix sums
freq = defaultdict(int)
# Initial prefix sum is 0 (empty prefix is considered balanced)
freq[0] = 1
# Traverse the array of strings
for i in range(n):
score = 0
# Calculate net score of current
# string: +1 for vowel, -1 for consonant
for ch in arr[i]:
if isVowel(ch):
score += 1
else:
score -= 1
# Update the running prefix sum
prefix += score
# If this prefix sum has been seen before,
# then the subarray between previous and
# current prefix is balanced
res += freq[prefix]
# Increment the frequency of this prefix sum
freq[prefix] += 1
return res
if __name__ == "__main__":
arr = ["aeio", "aa", "bc", "ot", "cdbd"]
print(countBalanced(arr))
using System;
using System.Collections.Generic;
class GfG
{
// Function to check if a character is a vowel
static bool isVowel(char ch)
{
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u';
}
// Function to count the number of balanced subarrays
static int countBalanced(string[] arr)
{
int n = arr.Length;
int res = 0;
int prefix = 0;
// Map to store frequency of prefix sums
Dictionary<int, int> freq = new Dictionary<int, int>();
// Initial prefix sum is 0 (empty prefix is considered balanced)
freq[0] = 1;
// Traverse the array of strings
for (int i = 0; i < n; i++)
{
int score = 0;
// Calculate net score of current
// string: +1 for vowel, -1 for consonant
foreach (char ch in arr[i])
{
if (isVowel(ch)) score++;
else score--;
}
// Update the running prefix sum
prefix += score;
// If this prefix sum has been seen before,
// then the subarray between previous and
// current prefix is balanced
if (freq.ContainsKey(prefix))
res += freq[prefix];
// Increment the frequency of this prefix sum
if (!freq.ContainsKey(prefix))
freq[prefix] = 0;
freq[prefix]++;
}
return res;
}
static void Main()
{
string[] arr = { "aeio", "aa", "bc", "ot", "cdbd" };
Console.WriteLine(countBalanced(arr));
}
}
// Function to check if a character is a vowel
function isVowel(ch) {
return 'aeiou'.includes(ch);
}
// Function to count the number of balanced subarrays
function countBalanced(arr) {
let n = arr.length;
let res = 0;
let prefix = 0;
// Map to store frequency of prefix sums
const freq = new Map();
// Initial prefix sum is 0 (empty prefix is considered balanced)
freq.set(0, 1);
// Traverse the array of strings
for (let i = 0; i < n; i++) {
let score = 0;
// Calculate net score of current
// string: +1 for vowel, -1 for consonant
for (let ch of arr[i]) {
if (isVowel(ch)) score++;
else score--;
}
// Update the running prefix sum
prefix += score;
// If this prefix sum has been seen before,
// then the subarray between previous and
// current prefix is balanced
res += freq.get(prefix) || 0;
// Increment the frequency of this prefix sum
freq.set(prefix, (freq.get(prefix) || 0) + 1);
}
return res;
}
// Driver Code
const arr = ["aeio", "aa", "bc", "ot", "cdbd"];
console.log(countBalanced(arr));
Time Complexity: O(n * l), where n is the number of strings and l is the average length of each string, since each character in all strings is processed once.
Space Complexity: O(n), due to the prefix sum frequency map which can store up to n unique prefix values.