Count Vowel Strings in Ranges

Updated on 16 May, 2025
Count Vowel Strings in Ranges header image

Problem Statement

In this problem, you are provided with an array of strings named words and a two-dimensional integer array queries. Each element of queries, denoted as queries[i] = [li, ri], requests you to determine how many strings within the subarray of words from index li to ri (inclusive) both commence and conclude with a vowel. The definition of vowels for this problem includes the characters 'a', 'e', 'i', 'o', and 'u'.

The objective is to compute the results for all these subarray queries and return them in an array ans, where each element ans[i] corresponds to the result of the i-th query in queries.

Examples

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 <= 105
  • 1 <= words[i].length <= 40
  • words[i] consists only of lowercase English letters.
  • sum(words[i].length) <= 3 * 105
  • 1 <= queries.length <= 105
  • 0 <= li <= ri < words.length

Approach and Intuition

To efficiently approach the given problem, follow these significant steps:

  1. Preprocess the List:

    • Iterate through the array words to check each string:
    • For each string, evaluate if it begins and ends with a vowel.
    • Create a boolean array vowelStartEnd where each index i carries True or False based on whether the corresponding index in words starts and ends with a vowel.
  2. Efficient Query Handling:

    • Given the potential size of the queries and words list, evaluating each query directly from the words list might be inefficient.
    • Utilize a cumulative sum technique on the vowelStartEnd. This involves creating a prefix sum array that holds the count of True values up to every index i.
    • For each query [li, ri], retrieve the count of True in the vowelStartEnd between these indices using the prefix sum array.
  3. Resolve Queries:

    • When resolving the queries, if li is 0, the result is directly the value at ri in the prefix sum array.
    • If li > 0, calculate the sum by subtracting the value at li-1 from the value at ri in the prefix sum array.
    • Populate each result into the results array ans corresponding to each query.

This approach ensures that you only preprocess the data once, and each query is resolved in constant time, which is efficient given the constraints. The preprocessing involves linear time complexity, and each query resolution is constant, yielding overall efficient time complexity for large inputs.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    vector<int> processWords(vector<string>& tokens,
                             vector<vector<int>>& requests) {
        vector<int> result(requests.size());
        unordered_set<char> vowelSet{'a', 'e', 'i', 'o', 'u'};
        vector<int> cumSum(tokens.size());
        int total = 0;
        for (int j = 0; j < tokens.size(); j++) {
            string word = tokens[j];
            if (vowelSet.count(word.front()) && vowelSet.count(word.back())) {
                total++;
            }
            cumSum[j] = total;
        }

        for (int j = 0; j < requests.size(); j++) {
            vector<int> query = requests[j];
            result[j] =
                cumSum[query[1]] -
                (query[0] == 0 ? 0 : cumSum[query[0] - 1]);
        }

        return result;
    }
};

The provided C++ solution focuses on counting words that start and end with vowels within specified ranges in a list of strings. The procedure embraces an efficient approach utilizing cumulative sums and optimization with the help of hash sets.

  • At the core, the solution introduces a class Solution with a method processWords that accepts two parameters: tokens, an array of words, and requests, which specifies ranges within the tokens array to examine.
  • The method initializes a result vector sized to the number of request ranges, dictating the count of words starting and ending with vowels per specified range.
  • An unordered set vowelSet is defined to quickly check if characters are vowels.
  • A cumulative sum array cumSum keeps a running total of how many words from the beginning up to the current index start and end with a vowel.
  • By looping through each word in tokens, update the cumulative sums. If a word starts and ends with a vowel, increment the total count.
  • For each query in requests, the method determines the count of qualifying words within the specified range by leveraging the precomputed cumulative sums. This subtraction approach derives the count of qualifying words without re-examining each subset individually, improving efficiency.
  • Finally, the result vector, representing the count of qualifying words for each request range, is returned.

Overall, this solution impressively optimizes the counting process by using cumulative sums and set operations, greatly reducing the computational overhead for multiple and possibly large query ranges.

java
class Solution {

    public int[] countVowelStrings(String[] inputWords, int[][] rangeQueries) {
        int[] result = new int[rangeQueries.length];
        HashSet<Character> vowelSet = new HashSet<>(
            Arrays.asList('a', 'e', 'i', 'o', 'u')
        );
        int[] cumulativeCount = new int[inputWords.length];
        int totalCount = 0;
        for (int index = 0; index < inputWords.length; index++) {
            String word = inputWords[index];
            if (
                vowelSet.contains(word.charAt(0)) &&
                vowelSet.contains(word.charAt(word.length() - 1))
            ) {
                totalCount++;
            }
            cumulativeCount[index] = totalCount;
        }

        for (int index = 0; index < rangeQueries.length; index++) {
            int[] query = rangeQueries[index];
            result[index] =
                cumulativeCount[query[1]] -
                (query[0] == 0 ? 0 : cumulativeCount[query[0] - 1]);
        }

        return result;
    }
}

This solution deals with counting vowel strings based on provided ranges, using Java as the programming language. The provided method countVowelStrings calculates how many words in the given list inputWords start and end with a vowel for specified queries.

  • Initialize a HashSet named vowelSet to quickly check if a character is a vowel.
  • An array cumulativeCount is used to hold the cumulative totals of words that start and end with vowels up to the current word as you iterate through the input words.
  • Iterate over the inputWords to populate the cumulativeCount. For each word, check if both the first and last characters are vowels (using vowelSet). If yes, increment the totalCount which keeps track of the cumulative total.
  • Next, for each query in rangeQueries:
    • Determine the number of words starting and ending with vowels in the specified range.
    • Subtract the cumulative count just before the start of the range from the cumulative count at the end of the range (correcting to 0 if the start of the range is 0).
    • Store this result in the result array.

This method effectively returns an array where each entry corresponds to the count of words meeting the vowel criteria for each corresponding query range in rangeQueries. Notably, this approach is efficient due to the use of cumulative counts, avoiding the need to re-calculate the number of valid words for overlapping range queries.

python
class Solution:
    def countVowelStrings(self, wordList: List[str], queryList: List[List[int]]) -> List[int]:
        results = [0] * len(queryList)
        vowel_set = {'a', 'e', 'i', 'o', 'u'}
        cumulative_count = [0] * len(wordList)
        total = 0
        
        for index, word in enumerate(wordList):
            if word[0] in vowel_set and word[-1] in vowel_set:
                total += 1
            cumulative_count[index] = total
        
        for query_index, query in enumerate(queryList):
            start, end = query[0], query[1]
            results[query_index] = cumulative_count[end] - (cumulative_count[start-1] if start > 0 else 0)
        
        return results

The provided solution in Python addresses the problem of counting the number of strings in specified ranges from a list, where each string begins and ends with a vowel. The solution uses an efficient approach by leveraging cumulative sums to quickly answer range queries about the number of qualifying vowel strings.

  • The solution defines a set, vowel_set, containing all vowel characters for quick lookup.
  • An array, cumulative_count, is initialized to track the cumulative number of strings that start and end with vowels up to each index in wordList.
  • As each word in wordList is processed, the code checks if both the first and last characters are vowels. If they are, the total count of such words is incremented.
  • This cumulative total is then stored in the cumulative_count array at the current index.
  • For each range query in queryList, the solution determines the count of strings that begin and end with a vowel by subtracting the cumulative values, levering precomputed results for efficiency.
  • The difference in the values from the cumulative_count array provides the result for each query, which is stored in the results array.

Thus, for each query, the algorithm efficiently computes the difference between the cumulative values without the need to re-inspect individual substrings or recalculate values, ensuring optimal performance even with a large number of queries or a large dataset.

Comments

No comments yet.