Count Vowel Strings in Ranges
MEDIUMDescription
You are given a 0-indexed array of strings words and a 2D array of integers queries.
Each query queries[i] = [li, ri] asks us to find the number of strings present at the indices ranging from li to ri (both inclusive) of words that start and end with a vowel.
Return an array ans of size queries.length, where ans[i] is the answer to the ith query.
Note that the vowel letters are 'a', 'e', 'i', 'o', and 'u'.
Example 1:
Input: words = ["aba","bcb","ece","aa","e"], queries = [[0,2],[1,4],[1,1]] Output: [2,3,0] Explanation: The strings starting and ending with a vowel are "aba", "ece", "aa" and "e". The answer to the query [0,2] is 2 (strings "aba" and "ece"). to query [1,4] is 3 (strings "ece", "aa", "e"). to query [1,1] is 0. We return [2,3,0].
Example 2:
Input: words = ["a","e","i"], queries = [[0,2],[0,1],[2,2]] Output: [3,2,1] Explanation: Every string satisfies the conditions, so we return [3,2,1].
Constraints:
1 <= words.length <= 1051 <= words[i].length <= 40words[i]consists only of lowercase English letters.sum(words[i].length) <= 3 * 1051 <= queries.length <= 1050 <= li <= ri < words.length
Approaches
Checkout 2 different approaches to solve Count Vowel Strings in Ranges. Click on different approaches to view the approach and algorithm in detail.
Prefix Sum Precomputation
A much more efficient approach is to precompute the counts to answer range queries quickly. The problem of finding the number of items with a certain property in a range is a classic application of the prefix sum technique. We can first determine for each word if it's a "vowel string" (starts and ends with a vowel). Then, we can build a prefix sum array on top of this information. The prefix sum array, prefixCounts, will store at index i the cumulative count of vowel strings from the beginning of the words array up to index i-1. With this prefixCounts array, the answer to any query [l, r] can be found in constant time by calculating prefixCounts[r+1] - prefixCounts[l].
Algorithm
- Create a prefix sum array,
prefixCounts, of sizeN + 1, whereNis the length of thewordsarray. InitializeprefixCounts[0] = 0. - Create a helper function
isVowel(char c). - Iterate through the
wordsarray fromi = 0toN-1. - For each
word, check if it starts and ends with a vowel. - Calculate the value for the current position in the prefix sum array:
prefixCounts[i+1] = prefixCounts[i] + (1 if the word is a vowel string, else 0). - After this single pass, the
prefixCountsarray is fully populated.prefixCounts[k]now holds the count of vowel strings inwords[0...k-1]. - Initialize an answer array
ansof sizeQ, whereQis the number of queries. - Iterate through each query
[l, r]. - The number of vowel strings in the range
[l, r]is the total count up to indexrminus the total count up to indexl-1. This can be calculated in O(1) time asprefixCounts[r + 1] - prefixCounts[l]. - Store this result in the
ansarray. - Return
ans.
This approach involves two main phases: precomputation and query processing.
In the precomputation phase, we iterate through the words array just once. We maintain a running count of vowel strings and store it in a prefixCounts array. prefixCounts[i+1] will store the total number of vowel strings found in the subarray words[0...i].
In the query processing phase, we can answer any range query [l, r] instantly. The count of vowel strings from index l to r is simply the total count up to r minus the total count up to l-1. Using our prefixCounts array, this translates to prefixCounts[r+1] - prefixCounts[l]. This decouples the query processing time from the size of the range, making it extremely fast.
class Solution {
private boolean isVowel(char c) {
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
public int[] vowelStrings(String[] words, int[][] queries) {
int n = words.length;
int[] prefixCounts = new int[n + 1];
// Build the prefix sum array
for (int i = 0; i < n; i++) {
String word = words[i];
int vowelFlag = 0;
if (isVowel(word.charAt(0)) && isVowel(word.charAt(word.length() - 1))) {
vowelFlag = 1;
}
prefixCounts[i + 1] = prefixCounts[i] + vowelFlag;
}
int[] ans = new int[queries.length];
for (int i = 0; i < queries.length; i++) {
int l = queries[i][0];
int r = queries[i][1];
// The count for range [l, r] is count(0..r) - count(0..l-1)
// which corresponds to prefixCounts[r+1] - prefixCounts[l]
ans[i] = prefixCounts[r + 1] - prefixCounts[l];
}
return ans;
}
}
Complexity Analysis
Pros and Cons
- Highly efficient, with linear time complexity.
- Answers each range query in constant time after the initial precomputation.
- Requires extra space proportional to the number of words to store the prefix sum array.
Code Solutions
Checking out 3 solutions in different languages for Count Vowel Strings in Ranges. Click on different languages to view the code.
Video Solution
Watch the video walkthrough for Count Vowel Strings in Ranges
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Companies:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.