Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
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.lengthProblem summary: 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'.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array
["aba","bcb","ece","aa","e"] [[0,2],[1,4],[1,1]]
["a","e","i"] [[0,2],[0,1],[2,2]]
jump-game-vii)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2559: Count Vowel Strings in Ranges
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;
}
}
// Accepted solution for LeetCode #2559: Count Vowel Strings in Ranges
func vowelStrings(words []string, queries [][]int) []int {
vowels := map[byte]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true}
nums := []int{}
for i, w := range words {
if vowels[w[0]] && vowels[w[len(w)-1]] {
nums = append(nums, i)
}
}
ans := make([]int, len(queries))
for i, q := range queries {
l, r := q[0], q[1]
ans[i] = sort.SearchInts(nums, r+1) - sort.SearchInts(nums, l)
}
return ans
}
# Accepted solution for LeetCode #2559: Count Vowel Strings in Ranges
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]
// Accepted solution for LeetCode #2559: Count Vowel Strings in Ranges
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #2559: Count Vowel Strings in Ranges
// 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;
// }
// }
// Accepted solution for LeetCode #2559: Count Vowel Strings in Ranges
function vowelStrings(words: string[], queries: number[][]): number[] {
const vowels = new Set(['a', 'e', 'i', 'o', 'u']);
const nums: number[] = [];
for (let i = 0; i < words.length; ++i) {
if (vowels.has(words[i][0]) && vowels.has(words[i][words[i].length - 1])) {
nums.push(i);
}
}
const search = (x: number): number => {
let l = 0,
r = nums.length;
while (l < r) {
const mid = (l + r) >> 1;
if (nums[mid] >= x) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
};
return queries.map(([l, r]) => search(r + 1) - search(l));
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.