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.
Build confidence with an intuition-first walkthrough focused on hash map fundamentals.
Given a string s, return true if s is a good string, or false otherwise.
A string s is good if all the characters that appear in s have the same number of occurrences (i.e., the same frequency).
Example 1:
Input: s = "abacbc" Output: true Explanation: The characters that appear in s are 'a', 'b', and 'c'. All characters occur 2 times in s.
Example 2:
Input: s = "aaabb" Output: false Explanation: The characters that appear in s are 'a' and 'b'. 'a' occurs 3 times while 'b' occurs 2 times, which is not the same number of times.
Constraints:
1 <= s.length <= 1000s consists of lowercase English letters.Problem summary: Given a string s, return true if s is a good string, or false otherwise. A string s is good if all the characters that appear in s have the same number of occurrences (i.e., the same frequency).
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map
"abacbc"
"aaabb"
rings-and-rods)make-number-of-distinct-characters-equal)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1941: Check if All Characters Have Equal Number of Occurrences
class Solution {
public boolean areOccurrencesEqual(String s) {
int[] cnt = new int[26];
for (char c : s.toCharArray()) {
++cnt[c - 'a'];
}
int v = 0;
for (int x : cnt) {
if (x == 0) {
continue;
}
if (v > 0 && v != x) {
return false;
}
v = x;
}
return true;
}
}
// Accepted solution for LeetCode #1941: Check if All Characters Have Equal Number of Occurrences
func areOccurrencesEqual(s string) bool {
cnt := [26]int{}
for _, c := range s {
cnt[c-'a']++
}
v := 0
for _, x := range cnt {
if x == 0 {
continue
}
if v > 0 && v != x {
return false
}
v = x
}
return true
}
# Accepted solution for LeetCode #1941: Check if All Characters Have Equal Number of Occurrences
class Solution:
def areOccurrencesEqual(self, s: str) -> bool:
return len(set(Counter(s).values())) == 1
// Accepted solution for LeetCode #1941: Check if All Characters Have Equal Number of Occurrences
struct Solution;
use std::collections::HashMap;
use std::collections::HashSet;
impl Solution {
fn are_occurrences_equal(s: String) -> bool {
let mut hm: HashMap<char, usize> = HashMap::new();
for c in s.chars() {
*hm.entry(c).or_default() += 1;
}
let mut hs: HashSet<usize> = HashSet::new();
for v in hm.values() {
hs.insert(*v);
}
hs.len() == 1
}
}
#[test]
fn test() {
let s = "abacbc".to_string();
let res = true;
assert_eq!(Solution::are_occurrences_equal(s), res);
let s = "aaabb".to_string();
let res = false;
assert_eq!(Solution::are_occurrences_equal(s), res);
}
// Accepted solution for LeetCode #1941: Check if All Characters Have Equal Number of Occurrences
function areOccurrencesEqual(s: string): boolean {
const cnt: number[] = Array(26).fill(0);
for (const c of s) {
++cnt[c.charCodeAt(0) - 'a'.charCodeAt(0)];
}
const v = cnt.find(v => v);
return cnt.every(x => !x || v === x);
}
Use this to step through a reusable interview workflow for this problem.
For each element, scan the rest of the array looking for a match. Two nested loops give n × (n−1)/2 comparisons = O(n²). No extra space since we only use loop indices.
One pass through the input, performing O(1) hash map lookups and insertions at each step. The hash map may store up to n entries in the worst case. This is the classic space-for-time tradeoff: O(n) extra memory eliminates an inner loop.
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.