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 jβˆ’ij - i.

The time complexity is O(n+mΓ—log⁑n)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;
}
};