Python 1941.py
class Solution:
def areOccurrencesEqual(self, s: str) -> bool:
freq = defaultdict(int)
for c in s:
freq[c] += 1
return min(freq.values()) == max(freq.values())
Difficulty
and has an acceptance rate of about 80% (200k+ submissions).
Typical patterns to solve this problem:
- Counting
- Hash Table
- String
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The provided implementation defines a Solution class with a single method areOccurrencesEqual. The method determines whether every distinct character in the input string s appears the same number of times. It returns True when all character frequencies are identical and False otherwise.
Key Steps
The algorithm proceeds through three distinct phases, each illustrated with a focused code excerpt.
Frequency Container Initialization
freq = defaultdict(int)
A defaultdict from the collections module is created with int as the default factory. This choice eliminates the need for explicit existence checks before incrementing a character’s count, allowing the code to treat missing keys as having a count of zero automatically.
Single-Pass Counting Loop
for c in s:
freq[c] += 1
The method iterates over every character c in the input string. For each character, the corresponding entry in freq is incremented. Because the container is a defaultdict, the first encounter of any character creates a new entry with an initial value of 0, which is then increased to 1. This loop runs exactly once over the input, guaranteeing linear processing relative to the length of s.
Equality Check of Extremal Frequencies
return min(freq.values()) == max(freq.values())
After the counting phase, the method extracts the collection of frequency values. It computes the smallest and largest values among them and compares them for equality. If the minimum and maximum are the same, every character count must be identical, and the method returns True; otherwise it returns False.
Edge Cases Handled
The implementation naturally accommodates strings that consist of a single repeated character. In such a case, the frequency dictionary contains a single entry, and both min and max return the same count, leading to a True result.
It also correctly processes strings containing a mixture of uppercase and lowercase letters, digits, punctuation, or any other Unicode code point, because the dictionary keys are the characters themselves without any transformation. The counting loop treats each distinct code point independently, ensuring that case sensitivity and symbol variety are respected.
When the input string contains multiple distinct characters that each appear the same number of times-such as "aabbcc" or "112233"-the frequency values are uniform, and the final comparison yields True. Conversely, any deviation in occurrence count, for example "aabbbc" where 'a' appears twice, 'b' three times, and 'c' once, results in differing min and max values, and the method returns False.
The use of defaultdict also sidesteps the need for explicit initialization of each character’s counter, which would otherwise require a conditional check for key existence. This design choice simplifies handling of characters that appear only once.
Performance Optimizations
The code exhibits several performance-focused decisions.
First, the counting phase executes in a single linear pass over the input string, avoiding any nested loops or repeated scans.
Second, employing defaultdict(int) removes the overhead of conditional key existence checks (if key in dict) that would be required with a plain dictionary. This results in fewer Python bytecode instructions per iteration.
Third, the final equality test leverages built-in min and max functions applied to the view returned by freq.values(). These functions are implemented in C and iterate over the values efficiently, providing a fast way to obtain the extremal frequencies without manual traversal.
Overall, the combination of a single pass, constant-time updates, and native C-level aggregation functions yields a solution that scales well with the size of the input string while maintaining concise and readable code.
ELI5 - Simplified Explanation
Imagine you have a big bucket full of different colored building blocks. You want to see if every color appears the exact same number of times.
First, you pick up each block one by one and put it into a special bag that remembers how many of each color you have found. You walk through the whole pile from the beginning to the end, counting every single block you see.
Once all the blocks are counted, you look at your tally for each color. You find the smallest number of blocks for any color and the largest number of blocks for any color. If those two numbers are the same, it means every color you have appears the same amount of times. If they are different, it means some colors have more blocks than others.
Code Quality
Complexity Analysis
As a rule of thumb, the maximum input size for one second execution time is
- factorial: up to 10 elements
- exponential: up to 20 elements
- polynomial: a few thousand elements
- loglinear: up to 100,000 elements
- linear: a few million elements
- logarithmic: a billion elements
- constant: practically unlimited
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| author | solutions | ||||||||||
| www | AlgoMonster | C++ | Python | Java | TS | ||||||
| WalkCCC | C++ | Python | Java | ||||||||
| leetcode.ca | C++ | Python | Java | Go | PHP | TS | |||||
| Progiez | C++ | Python | Java | ||||||||
| github | black-shadows | C++ | |||||||||
| chandansgowda | Python | ||||||||||
| charles-wangkai | Java | ||||||||||
| DimitrisJim | C | ||||||||||
| everthis | JS | ||||||||||
| fartem | Ruby | ||||||||||
| fsq | C++ | ||||||||||
| JoshCrozier | JS | ||||||||||
| lkwq007 | Python | ||||||||||
| muhammadfarhankt | Go | ||||||||||
| suxrobGM | C# | ||||||||||
| varunu28 | Java | ||||||||||
| AlgoMonster | C++, Python, Java, TypeScript | ||||||||||
| WalkCCC | C++, Python, Java | ||||||||||
| leetcode.ca | C++, Go, Java, PHP, Python, TypeScript | ||||||||||
| Progiez | C++, Java, Python | ||||||||||
| black-shadows | C++, C++ | ||||||||||
| chandansgowda | Python | ||||||||||
| charles-wangkai | Java | ||||||||||
| DimitrisJim | C | ||||||||||
| everthis | JavaScript | ||||||||||
| fartem | Ruby | ||||||||||
| fsq | C++ | ||||||||||
| JoshCrozier | JavaScript | ||||||||||
| lkwq007 | Python | ||||||||||
| muhammadfarhankt | Go | ||||||||||
| suxrobGM | C# | ||||||||||
| varunu28 | Java |
Videos
Similar Problems
- problem 2103: Rings and Rods
- problem 2531: Make Number of Distinct Characters Equal
Solved On The Same Day
- problem 1925: Count Square Sum Triples
- problem 1974: Minimum Time to Type Word Using Special Typewriter
- problem 1936: Add Minimum Number of Rungs
- problem 1953: Maximum Number of Weeks for Which You Can Work
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality