↓Skip to main content
  1. LeetCode/

LeetCode 3306: Count of Substrings Containing Every Vowel and K Consonants II

·2 mins· ·
LeetCode Medium Sliding-Window Hash-Table String
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2026-01-21

  • Submissions: Wrong Answer ×2 → Accepted → Runtime Error → Accepted

Approach
#

“Exactly k consonants” is not monotonic. But “all five vowels and at least m consonants” is (a larger window only makes it easier), so:

exactly k = at least k − at least k + 1

The “at least” count: shrink while valid until invalid, then count += left.

My Attempts
#

My version took another route: with exactly k consonants, extra vowels on the left can be dropped or kept, so extra tracked “how many more vowels can be dropped on the left”, adding 1 + extra per right end.

VersionProblem
Attempt 1Added only 1 per right end, ignoring the extra vowels on the left. For word = "euioeaa", k = 0, the answer is 4; it returned 2
Attempt 2Added extra, but as a local variable reset to 0 every round. Extra vowels dropped in earlier rounds were no longer counted; the same example returned 3
ACMoved extra outside the loop, resetting it only when too many consonants forced a consonant out
REA rewrite put extra = 0 inside the consonant-shrinking loop, so when no shrink happened extra was undefined: UnboundLocalError
ACMoved the initialization back outside the loop

The extra approach works, but needs care about when to reset it; the at-least difference needs no extra state.

Solution
#

class Solution:
    def countOfSubstrings(self, word: str, k: int) -> int:
        def at_least(m: int) -> int:               # all five vowels, at least m consonants
            vowels = Counter()
            consonants = left = count = 0
            for c in word:
                if c in "aeiou":
                    vowels[c] += 1
                else:
                    consonants += 1
                while len(vowels) == 5 and consonants >= m:
                    d = word[left]
                    if d in "aeiou":
                        vowels[d] -= 1
                        if vowels[d] == 0:
                            del vowels[d]
                    else:
                        consonants -= 1
                    left += 1
                count += left
            return count

        return at_least(k) - at_least(k + 1)

Complexity
#

Time O(n), space O(1).

Mistakes to Avoid
#

  • Sliding directly on “exactly”: not monotonic, and extra vowels on the left get missed.
  • With the extra approach, reset it only when a consonant leaves.

Interview Explanation
#

“Exactly k consonants” is not monotonic, so I compute “at least k” minus “at least k + 1”. “All five vowels and at least m consonants” is monotonic, so an “at least” sliding window shrinks while valid, and every left end from 0 to left - 1 is valid, so I add left. Time O(n).

Related

LeetCode 1358: Number of Substrings Containing All Three Characters
·2 mins
LeetCode Medium Sliding-Window Hash-Table String
LeetCode 1358 note: an “at least one each of a, b, c” counting window: keep shrinking while all three are present, then count += left
LeetCode 3325: Count Substrings With K-Frequency Characters I
·2 mins
LeetCode Medium Sliding-Window Hash-Table String
LeetCode 3325 note: an “at least one character appears k times” counting window; when the new character reaches k, keep shrinking until it drops to k - 1
LeetCode 395: Longest Substring with At Least K Repeating Characters
·3 mins
LeetCode Medium Sliding-Window Divide-and-Conquer Hash-Table String
LeetCode 395 note: “every character at least k times” is not monotonic, so a direct slide fails; divide and conquer splits on characters with fewer than k occurrences, or fixing the number of distinct characters makes the window slidable
LeetCode 2516: Take K of Each Character From Left and Right
·2 mins
LeetCode Medium Sliding-Window Hash-Table String
LeetCode 2516 note: taking from both ends leaves a middle block in which each letter may appear at most total − k times; find the longest such window
LeetCode 1016: Binary String With Substrings Representing 1 To N
·3 mins
LeetCode Medium Sliding-Window String Bit-Manipulation Hash-Table
LeetCode 1016 note: s has at most 1000 characters, so there are few substrings of any fixed length and a large n must be False; checking from n downward fails fast, or extend up to 30 bits from each start to collect every value <= n
LeetCode 3694: Distinct Points Reachable After Substring Removal
·2 mins
LeetCode Medium Sliding-Window Prefix-Sum Hash-Table String
LeetCode 3694 note: the endpoint is the total displacement minus the removed segment’s displacement; a length-k window tracks that segment and each endpoint goes into a set