2063. Vowels of All Substrings
Problem Description
The task is to calculate the total number of vowels present in all possible substrings of a given string, word
. Vowels are the characters 'a', 'e', 'i', 'o', and 'u'. A substring is defined as any continuous sequence of characters within the string. It's important to note that since we are counting vowels in every possible substring, a single vowel can contribute to the count multiple times, depending on its position in the string and the number of substrings that include it. Also, the total count may be very large, so special attention should be paid to avoid integer overflow during the calculation.
Intuition
To find the solution without checking every possible substring directly, we can consider how many times each vowel contributes to the total count. A character at position i
in the string word
of length n
is part of i + 1
substrings starting at or before position i
and part of n - i
substrings ending at or after position i
. Therefore, that character is found in a total of (i + 1) * (n - i)
substrings.
By looping through the characters of the word and checking if each character is a vowel, we can use the above formula to count how many times each vowel appears across all substrings. Then, summing these counts gives us the total number of vowels in all substrings. Python's list comprehension makes this process concise and efficient, as seen in the provided solution. This approach significantly reduces the computational complexity compared to the naive approach of generating and checking every possible substring individually.
Learn more about Math, Dynamic Programming and Combinatorics patterns.
Solution Approach
The solution to this problem utilizes a single-pass algorithm along with the mathematical concept that each character in a string contributes to several substrings based on its position.
Here's a walk-through of the implementation steps with reference to the provided Python code:
- We determine the length
n
of the stringword
. - We initialize a total sum of vowel occurrences in all substrings, which will be our final result. This sum starts at 0.
- We then iterate through the string
word
using a for loop withenumerate
, which gives us each characterc
along with its indexi
. - Within the loop, we check if the current character
c
is a vowel. This is accomplished by checking ifc
is in the string'aeiou'
. - For every vowel found, we calculate its contribution to the total count. The number of times this vowel appears in all substrings is given by
(i + 1) * (n - i)
, wherei + 1
is the number of possible starting points for substrings that include this character, andn - i
is the number of possible ending points. - We add this contribution to the total sum for each vowel encountered.
- Finally, the total sum is returned as the result.
The provided solution uses a concise list comprehension that combines these steps into a single line. The sum
function calculates the aggregate total by adding up the contributions from each vowel character in the string. Here's the core logic in the code:
sum((i + 1) * (n - i) for i, c in enumerate(word) if c in 'aeiou')
This solution is efficient because it only involves processing each character of the string once and does not require generating all substrings explicitly. It has a time complexity of O(n), where n is the length of the string since it iterates through the string once, and each operation within the loop is constant time. There's no complex data structure used, and the space complexity is O(1) as it only keeps track of the total sum and loop variables.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's go through an example to illustrate the solution approach using the string word = "abcde"
.
-
First, we determine the length of the string
word
, which isn = 5
. -
We initialize the total sum of vowel occurrences in all substrings to 0. This will hold our result.
-
Now, we iterate through the string
word
. For each iteration, we consider both the characterc
and its indexi
. -
Let's walk through each character of the string
abcde
:-
For character
a
at indexi = 0
:- We check if
a
is a vowel — yes, it is. - We calculate its contribution:
(0 + 1) * (5 - 0) = 5
. - We add this to the total sum, so the sum is now 5.
- We check if
-
For character
b
at indexi = 1
:b
is not a vowel, so we do not count it.
-
For character
c
at indexi = 2
:c
is also not a vowel, so we continue.
-
For character
d
at indexi = 3
:d
is not a vowel, so we skip it as well.
-
For character
e
at indexi = 4
:- We check if
e
is a vowel — it is. - We calculate its contribution:
(4 + 1) * (5 - 4) = 5
. - We add this to the total sum, which becomes
5 (from a) + 5 (from e) = 10
.
- We check if
-
-
Since there are no more characters in the string, we have completed our iteration. The total vowel occurrences in all possible substrings of
"abcde"
equal 10. -
We return 10 as the final result.
This walkthrough demonstrates the core logic of the provided Python code:
sum((i + 1) * (5 - i) for i, c in enumerate("abcde") if c in 'aeiou')
By following these steps, we efficiently calculate the total number of vowel occurrences in all possible substrings of a given string.
Solution Implementation
1class Solution:
2 def count_vowels(self, word: str) -> int:
3 # Calculate the length of the word
4 word_length = len(word)
5
6 # Initialize a variable to hold the total count of vowels in all substrings
7 vowel_count = 0
8
9 # Iterate through each character in the word along with its index
10 for index, char in enumerate(word):
11 # Check if the current character is a vowel
12 if char in 'aeiou':
13 # If it's a vowel, calculate the contribution of this vowel to the total count
14 # The vowel contributes to all substrings that start before (or at) this character
15 # and end after (or at) this character. The number of such substrings can be calculated
16 # by multiplying the number of ways to choose a start point (index + 1 choices) by
17 # the number of ways to choose an end point (word_length - index choices).
18 contribution = (index + 1) * (word_length - index)
19 # Add the contribution of this vowel to the total count
20 vowel_count += contribution
21
22 # Return the total count of vowels in all substrings
23 return vowel_count
24
1class Solution {
2 public long countVowels(String word) {
3 long totalCount = 0; // Initialize total count of vowels in substrings
4 int wordLength = word.length(); // Cache the length of the word for efficiency
5
6 // Iterate over each character in the word
7 for (int i = 0; i < wordLength; ++i) {
8 char currentChar = word.charAt(i); // Get the character at the current index
9
10 // Check if the current character is a vowel
11 if (currentChar == 'a' || currentChar == 'e' || currentChar == 'i' || currentChar == 'o' || currentChar == 'u') {
12 // If it's a vowel, add to the total count based on its position and remaining length
13 // The count is the product of the number of times this vowel can appear in
14 // the start of a substring (i+1 times) and in the end of a substring (wordLength - i times)
15 totalCount += (long) (i + 1) * (wordLength - i);
16 }
17 }
18
19 // Return the total count of vowels found in all the substrings
20 return totalCount;
21 }
22}
23
1class Solution {
2public:
3 // Function to count the total number of vowel appearances in all substrings of the word.
4 long long countVowels(string word) {
5 long long totalVowels = 0; // Initialize a variable to keep track of the total vowels count.
6 int wordLength = word.size(); // Find the length of the word once to avoid multiple calls to `size()`.
7
8 // Loop through each character of the word.
9 for (int i = 0; i < wordLength; ++i) {
10 char currentChar = word[i]; // Store the current character to compare it against vowels.
11
12 // Check if the character is a vowel - 'a', 'e', 'i', 'o', or 'u'.
13 if (currentChar == 'a' || currentChar == 'e' || currentChar == 'i' ||
14 currentChar == 'o' || currentChar == 'u') {
15 // The number of times this vowel character will appear in all possible substrings
16 // is the product of its position (1-indexed) and its "rightward reach" (n - i).
17 totalVowels += (static_cast<long long>(i) + 1) * (wordLength - i);
18 }
19 }
20
21 // Return the total count of vowel appearances in all substrings.
22 return totalVowels;
23 }
24};
25
1// Function to count the total number of vowels in a given string, where each vowel
2// is counted as many times as it contributes to each possible substring.
3// @param {string} word - The word to count vowels in
4// @returns {number} - The total count of vowels contributing to substrings
5function countVowels(word: string): number {
6 const wordLength = word.length;
7 let vowelCount = 0;
8
9 // Loop over all characters in the word
10 for (let index = 0; index < wordLength; ++index) {
11 // Check if the current character is a vowel
12 if (['a', 'e', 'i', 'o', 'u'].includes(word[index])) {
13 // If it is a vowel, add the count to the running total, factoring in
14 // the number of possible substrings it can be part of:
15 // Multiply the position of the vowel in the string (index + 1)
16 // by the number of ways to choose the ending of the substring (wordLength - index)
17 vowelCount += (index + 1) * (wordLength - index);
18 }
19 }
20
21 // Return the total count of vowels
22 return vowelCount;
23}
24
Time and Space Complexity
The given Python code snippet defines a function that counts the number of times a vowel appears in a string, such that each occurrence of a vowel is counted as many times as the number of substrings that include it.
Time Complexity: O(n)
The time complexity of the function is O(n) where n
is the length of the input string word
. This is because the function contains a single loop (created by the sum
function and list comprehension) that iterates over each character in the string exactly once. Inside the loop, each step involves simple arithmetic operations that are constant time, namely (i + 1) * (n - i)
, and a membership test c in 'aeiou'
, which is also constant time since the set of vowels is of fixed size.
The calculation of the arithmetic progression is done for each vowel character in the string, thus the total operations scale linearly with the size of the input n
.
Space Complexity: O(1)
The space complexity of the function is O(1). There are no data structures used that grow with the input size. Temporary variables like i
and c
are reused for each character in the string. The string 'aeiou'
is a constant space that does not change with the input. Thus, the algorithm uses a fixed amount of space regardless of the size of the input.
Learn more about how to find time and space complexity quickly using problem constraints.
How many times is a tree node visited in a depth first search?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
What is Dynamic Programming Prerequisite DFS problems dfs_intro Backtracking problems backtracking Memoization problems memoization_intro Pruning problems backtracking_pruning Dynamic programming is an algorithmic optimization technique that breaks down a complicated problem into smaller overlapping sub problems in a recursive manner and uses solutions to the sub problems to construct a solution
Backtracking Template Prereq DFS with States problems dfs_with_states Combinatorial search problems Combinatorial search problems involve finding groupings and assignments of objects that satisfy certain conditions Finding all permutations combinations subsets and solving Sudoku are classic combinatorial problems The time complexity of combinatorial problems often grows rapidly with the size of
Want a Structured Path to Master System Design Too? Don’t Miss This!