Python 2283.py
class Solution:
def digitCount(self, num: str) -> bool:
freq = [ 0 ] * 10
for n in num:
freq[int(n)] += 1
return all(int(n) == f for n, f in zip(num, freq))
Difficulty
and has an acceptance rate of about 73% (100k+ 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 solves the “digit count” verification problem: given a numeric string num, it checks whether each digit i (0-9) appears exactly i times in the string. The method returns True when the condition holds for every position, otherwise False. The solution follows a straightforward two-phase approach: first it tallies the occurrences of each digit, then it validates the tallied counts against the characters of the original string.
Frequency Accumulation
The first logical block creates a fixed-size list freq with ten slots, each initialized to zero. This list serves as a counter for the ten possible digit values.
freq = [ 0 ] * 10
A single loop iterates over every character n in the input string. The character is converted to an integer index, and the corresponding slot in freq is incremented.
for n in num:
freq[int(n)] += 1
Because the list size is constant (ten elements), the memory footprint remains unchanged regardless of the length of num. The loop processes each character exactly once, ensuring that the counting phase scales linearly with the input size.
Validation of Counts
After the frequency table is populated, the method uses the built-in all function together with a generator expression to compare each digit in the original string with the count stored at the same index in freq.
return all(int(n) == f for n, f in zip(num, freq))
The zip function pairs each character n from num with the corresponding frequency f from freq. The generator yields a Boolean for each pair, asserting that the numeric value of the character equals the recorded frequency. The all wrapper short-circuits as soon as a mismatch is found, immediately returning False without evaluating the remaining pairs.
Edge-Case Handling
The algorithm naturally accommodates several edge conditions:
-
Empty string - When
numis empty, the frequency list stays at all zeros. Thezipcall produces no pairs, andallon an empty iterable returnsTrue. This aligns with the definition that an empty string trivially satisfies the condition (no digit claims any occurrences). -
Leading zeros - Characters
'0'are counted like any other digit. Since the condition requires the digit0to appear zero times, any occurrence of'0'will cause a mismatch, and the function will correctly returnFalse. -
Non-digit characters - The code assumes that every character can be safely converted with
int(n). In the intended problem domain the input is guaranteed to consist solely of digits, so the conversion never raises an exception. -
Strings longer than ten characters - The algorithm does not impose a length limit. Even if the string contains more than ten characters, the counting and validation steps remain valid because the frequency list still covers all possible digit values.
Performance Optimizations
Several design choices contribute to efficient execution:
-
Fixed-size counter array - Using a list of ten integers avoids the overhead of dynamic data structures such as dictionaries or collections.Counter. Indexing into a list is a constant-time operation, and the fixed size eliminates any need for resizing.
-
In-place increment - The loop updates the counter directly without creating intermediate objects, minimizing allocation pressure during the counting phase.
-
Generator expression with
all- The validation step does not construct an intermediate list of Boolean results. The generator yields values on demand, andallstops at the first failure, preventing unnecessary comparisons when the string is invalid early in the sequence. -
Single pass for counting - By separating counting from validation, the algorithm ensures that each character is examined only once for counting, and then only once more for validation (if needed). This two-pass structure is optimal for the problem because the required information (frequency of each digit) must be known before any comparison can be made.
Overall, the implementation delivers a concise and performant solution that leverages Python’s built-in constructs to keep both time and memory usage low while correctly handling the defined edge cases.
ELI5 - Simplified Explanation
Imagine you have a long row of numbered buckets sitting on the floor, and each bucket is waiting to hold a special collection of toys. You have a message made of numbers, and each number is like a little label telling you how many of that specific toy to gather.
First, you look at every single number in your message one by one. If you see a number like three, you walk over to the bucket labeled three and put a shiny marble inside it. If you see a five, you walk over to the bucket labeled five and drop a marble there. By the time you finish reading the whole message, the buckets act like a tally board that remembers exactly how many times each number showed up.
Finally, you go back to the start of the message and check the work. You look at the first number in the message and ask if the number of marbles in the corresponding bucket matches what the message said. You do this for every single position to make sure the message is telling the truth about how many times each digit appears. It is like checking a grocery list to make sure every item you put in your cart matches what was written down.
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 | Python | Java | C++ | TS | |||||
| WalkCCC | Python | Java | C++ | |||||||
| leetcode.ca | Python | Java | C++ | C | Go | Rust | TS | |||
| Progiez | Python | Java | C++ | |||||||
| github | chandansgowda | Python | ||||||||
| charles-wangkai | Java | |||||||||
| fartem | Ruby | |||||||||
| fsq | C++ | |||||||||
| JoshCrozier | JS | |||||||||
| lkwq007 | Python | |||||||||
| varunu28 | Java | |||||||||
| AlgoMonster | C++, Python, Java, TypeScript | |||||||||
| WalkCCC | C++, Python, Java | |||||||||
| leetcode.ca | C, C++, Go, Java, Python, Rust, TypeScript | |||||||||
| Progiez | C++, Java, Python | |||||||||
| chandansgowda | Python | |||||||||
| charles-wangkai | Java | |||||||||
| fartem | Ruby | |||||||||
| fsq | C++ | |||||||||
| JoshCrozier | JavaScript | |||||||||
| lkwq007 | Python | |||||||||
| varunu28 | Java |
Videos
Similar Problems
- problem 728: Self Dividing Numbers
Solved On The Same Day
- problem 2287: Rearrange Characters to Make Target String
- problem 2293: Min Max Game
- problem 2275: Largest Combination With Bitwise AND Greater Than Zero
- problem 2311: Longest Binary Subsequence Less Than or Equal to K
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