Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Move from brute-force thinking to an efficient approach using hash map strategy.
Given a string s, return the maximum number of occurrences of any substring under the following rules:
maxLetters.minSize and maxSize inclusive.Example 1:
Input: s = "aababcaab", maxLetters = 2, minSize = 3, maxSize = 4 Output: 2 Explanation: Substring "aab" has 2 occurrences in the original string. It satisfies the conditions, 2 unique letters and size 3 (between minSize and maxSize).
Example 2:
Input: s = "aaaa", maxLetters = 1, minSize = 3, maxSize = 3 Output: 2 Explanation: Substring "aaa" occur 2 times in the string. It can overlap.
Constraints:
1 <= s.length <= 1051 <= maxLetters <= 261 <= minSize <= maxSize <= min(26, s.length)s consists of only lowercase English letters.Problem summary: Given a string s, return the maximum number of occurrences of any substring under the following rules: The number of unique characters in the substring must be less than or equal to maxLetters. The substring size must be between minSize and maxSize inclusive.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Sliding Window
"aababcaab" 2 3 4
"aaaa" 1 3 3
rearrange-characters-to-make-target-string)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1297: Maximum Number of Occurrences of a Substring
class Solution {
public int maxFreq(String s, int maxLetters, int minSize, int maxSize) {
int ans = 0;
Map<String, Integer> cnt = new HashMap<>();
for (int i = 0; i < s.length() - minSize + 1; ++i) {
String t = s.substring(i, i + minSize);
Set<Character> ss = new HashSet<>();
for (int j = 0; j < minSize; ++j) {
ss.add(t.charAt(j));
}
if (ss.size() <= maxLetters) {
cnt.merge(t, 1, Integer::sum);
ans = Math.max(ans, cnt.get(t));
}
}
return ans;
}
}
// Accepted solution for LeetCode #1297: Maximum Number of Occurrences of a Substring
func maxFreq(s string, maxLetters int, minSize int, maxSize int) (ans int) {
cnt := map[string]int{}
for i := 0; i < len(s)-minSize+1; i++ {
t := s[i : i+minSize]
ss := map[rune]bool{}
for _, c := range t {
ss[c] = true
}
if len(ss) <= maxLetters {
cnt[t]++
if ans < cnt[t] {
ans = cnt[t]
}
}
}
return
}
# Accepted solution for LeetCode #1297: Maximum Number of Occurrences of a Substring
class Solution:
def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int:
ans = 0
cnt = Counter()
for i in range(len(s) - minSize + 1):
t = s[i : i + minSize]
ss = set(t)
if len(ss) <= maxLetters:
cnt[t] += 1
ans = max(ans, cnt[t])
return ans
// Accepted solution for LeetCode #1297: Maximum Number of Occurrences of a Substring
use std::collections::{HashMap, HashSet};
impl Solution {
pub fn max_freq(s: String, max_letters: i32, min_size: i32, _max_size: i32) -> i32 {
let n = s.len();
let m = min_size as usize;
let max_letters = max_letters as usize;
let bytes = s.as_bytes();
let mut cnt: HashMap<&[u8], i32> = HashMap::new();
let mut ans = 0;
for i in 0..=n - m {
let t = &bytes[i..i + m];
let mut set = HashSet::new();
for &c in t {
set.insert(c);
if set.len() > max_letters {
break;
}
}
if set.len() <= max_letters {
let v = cnt.entry(t).or_insert(0);
*v += 1;
ans = ans.max(*v);
}
}
ans
}
}
// Accepted solution for LeetCode #1297: Maximum Number of Occurrences of a Substring
function maxFreq(s: string, maxLetters: number, minSize: number, maxSize: number): number {
const cnt = new Map<string, number>();
let ans = 0;
for (let i = 0; i < s.length - minSize + 1; ++i) {
const t = s.slice(i, i + minSize);
const ss = new Set(t.split(''));
if (ss.size <= maxLetters) {
cnt.set(t, (cnt.get(t) || 0) + 1);
ans = Math.max(ans, cnt.get(t)!);
}
}
return ans;
}
Use this to step through a reusable interview workflow for this problem.
For each starting index, scan the next k elements to compute the window aggregate. There are n−k+1 starting positions, each requiring O(k) work, giving O(n × k) total. No extra space since we recompute from scratch each time.
The window expands and contracts as we scan left to right. Each element enters the window at most once and leaves at most once, giving 2n total operations = O(n). Space depends on what we track inside the window (a hash map of at most k distinct elements, or O(1) for a fixed-size window).
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Using `if` instead of `while` leaves the window invalid for multiple iterations.
Usually fails on: Over-limit windows stay invalid and produce wrong lengths/counts.
Fix: Shrink in a `while` loop until the invariant is valid again.