Skip to main content

Count Vowel Strings in Ranges

Problem Description

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 in the range 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'.

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 <= 10^5
  • 1 <= words[i].length <= 40
  • sum(words[i].length) <= 3 * 10^5

Approach

We can preprocess all the indices of the strings that start and end with a vowel, and record them in order in the array numsnums.

Next, we iterate through each query (l,r)(l, r), and use binary search to find the first index ii in numsnums that is greater than or equal to ll, and the first index jj that is greater than rr. Therefore, the answer to the current query is jij - i.

The time complexity is O(n+m×logn)O(n + m \times \log n), and the space complexity is O(n)O(n). Where nn and mm are the lengths of the arrays wordswords and queriesqueries, respectively.

Python3

class Solution:
def vowelStrings(self, words: List[str], queries: List[List[int]]) -> List[int]:
vowels = set("aeiou")
nums = [i for i, w in enumerate(words) if w[0] in vowels and w[-1] in vowels]
return [bisect_right(nums, r) - bisect_left(nums, l) for l, r in queries]

Java

class Solution {
private List<Integer> nums = new ArrayList<>();

public int[] vowelStrings(String[] words, int[][] queries) {
Set<Character> vowels = Set.of('a', 'e', 'i', 'o', 'u');
for (int i = 0; i < words.length; ++i) {
char a = words[i].charAt(0), b = words[i].charAt(words[i].length() - 1);
if (vowels.contains(a) && vowels.contains(b)) {
nums.add(i);
}
}
int m = queries.length;
int[] ans = new int[m];
for (int i = 0; i < m; ++i) {
int l = queries[i][0], r = queries[i][1];
ans[i] = search(r + 1) - search(l);
}
return ans;
}

private int search(int x) {
int l = 0, r = nums.size();
while (l < r) {
int mid = (l + r) >> 1;
if (nums.get(mid) >= x) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
}

C++

class Solution {
public:
vector<int> vowelStrings(vector<string>& words, vector<vector<int>>& queries) {
unordered_set<char> vowels = {'a', 'e', 'i', 'o', 'u'};
vector<int> nums;
for (int i = 0; i < words.size(); ++i) {
char a = words[i][0], b = words[i].back();
if (vowels.count(a) && vowels.count(b)) {
nums.push_back(i);
}
}
vector<int> ans;
for (auto& q : queries) {
int l = q[0], r = q[1];
int cnt = upper_bound(nums.begin(), nums.end(), r) - lower_bound(nums.begin(), nums.end(), l);
ans.push_back(cnt);
}
return ans;
}
};