2283. Check if Number Has Equal Digit Count and Digit Value
Problem Description
You are given a string num
that contains only digits. The string is 0-indexed with length n
.
The problem asks you to check if the string satisfies a special property: for every position i
in the string (where 0 <= i < n
), the digit i
should appear exactly num[i]
times throughout the entire string.
In other words:
- At position 0, if the character is '3', then the digit 0 should appear exactly 3 times in the entire string
- At position 1, if the character is '2', then the digit 1 should appear exactly 2 times in the entire string
- At position 2, if the character is '1', then the digit 2 should appear exactly 1 time in the entire string
- And so on for each position...
Return true
if this condition holds for every position in the string, otherwise return false
.
For example, if num = "1210"
:
- Position 0 has '1', so digit 0 should appear 1 time (it appears once at position 3) ✓
- Position 1 has '2', so digit 1 should appear 2 times (it appears twice at positions 0 and 2) ✓
- Position 2 has '1', so digit 2 should appear 1 time (it appears once at position 1) ✓
- Position 3 has '0', so digit 3 should appear 0 times (it doesn't appear) ✓
- All conditions are satisfied, so return
true
Intuition
The key insight is that we need to verify a relationship between positions and digit frequencies. Since we need to check if digit i
appears exactly num[i]
times in the string, we need two pieces of information:
- How many times each digit actually appears in the string
- What value is at each position
The natural approach is to first count all digit occurrences, then verify each position's requirement. We can think of this as a two-pass approach:
First pass: Count how many times each digit (0-9) appears in the entire string. This gives us the actual frequency of each digit.
Second pass: For each position i
, check if the actual count of digit i
matches the expected count num[i]
.
Why does this work? Because the problem essentially asks us to validate a "self-describing" property of the string. Each position describes how many times its index (as a digit) should appear. By pre-counting all frequencies, we can efficiently verify each position's claim in a single pass.
The solution uses Counter
to quickly count digit frequencies, converting each character to an integer. Then it uses all()
with a generator expression to check if every position satisfies its requirement: cnt[i] == int(x)
where i
is the position (which represents the digit we're checking) and x
is the character at that position (which tells us the expected count).
This approach is efficient because we only need to traverse the string twice - once for counting and once for verification - giving us O(n)
time complexity.
Solution Approach
The solution uses a counting and enumeration approach to verify the self-describing property of the string.
Step 1: Count digit frequencies
cnt = Counter(int(x) for x in num)
We use Python's Counter
from the collections module to count how many times each digit appears in the string. The expression int(x) for x in num
converts each character in the string to an integer (e.g., '3' becomes 3). The Counter
creates a dictionary-like object where:
- Keys are the digits that appear in the string
- Values are their occurrence counts
For example, if num = "1210"
, then cnt
would be {1: 2, 2: 1, 0: 1}
, meaning digit 1 appears twice, digit 2 appears once, and digit 0 appears once.
Step 2: Verify each position's requirement
return all(cnt[i] == int(x) for i, x in enumerate(num))
We use enumerate(num)
to iterate through each position i
and its corresponding character x
in the string. For each position:
i
represents the digit we need to check (the position index)int(x)
represents the expected count (the value at that position)cnt[i]
gives us the actual count of digiti
in the string
The all()
function returns True
only if every position satisfies the condition cnt[i] == int(x)
. If any position fails this check, it returns False
.
Note that cnt[i]
returns 0 if digit i
doesn't exist in the counter, which correctly handles cases where a digit should appear 0 times.
Time Complexity: O(n)
where n
is the length of the string - we traverse the string twice (once for counting, once for verification).
Space Complexity: O(1)
since we only store counts for at most 10 digits (0-9).
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with num = "2020"
:
Step 1: Count digit frequencies
- First, we count how many times each digit appears in the string
- Going through "2020": digit 2 appears twice, digit 0 appears twice
cnt = {2: 2, 0: 2}
Step 2: Verify each position's requirement
Now we check if each position i
has the correct value:
-
Position 0:
- Character is '2', so digit 0 should appear 2 times
- Check:
cnt[0] == 2
? →2 == 2
✓
-
Position 1:
- Character is '0', so digit 1 should appear 0 times
- Check:
cnt[1] == 0
? →0 == 0
✓ (cnt[1] returns 0 since digit 1 isn't in the counter)
-
Position 2:
- Character is '2', so digit 2 should appear 2 times
- Check:
cnt[2] == 2
? →2 == 2
✓
-
Position 3:
- Character is '0', so digit 3 should appear 0 times
- Check:
cnt[3] == 0
? →0 == 0
✓ (cnt[3] returns 0 since digit 3 isn't in the counter)
All positions satisfy their requirements, so the function returns true
.
Another example with num = "1211"
:
Step 1: Count frequencies
cnt = {1: 2, 2: 2}
Step 2: Verify each position
- Position 0: digit 0 should appear 1 time, but
cnt[0] = 0
→0 ≠ 1
✗
Since position 0 fails the check, the function returns false
immediately.
Solution Implementation
1from collections import Counter
2
3class Solution:
4 def digitCount(self, num: str) -> bool:
5 # Count the frequency of each digit in the string
6 # Convert each character to integer before counting
7 digit_frequency = Counter(int(digit) for digit in num)
8
9 # Check if each position satisfies the condition:
10 # The digit at index i should equal the count of digit i in the entire string
11 # For all indices, verify that frequency of index value equals the digit at that position
12 return all(digit_frequency[index] == int(digit_at_index)
13 for index, digit_at_index in enumerate(num))
14
1class Solution {
2 public boolean digitCount(String num) {
3 // Array to store the frequency count of each digit (0-9)
4 int[] digitFrequency = new int[10];
5 int length = num.length();
6
7 // Count the occurrence of each digit in the string
8 for (int i = 0; i < length; i++) {
9 int digit = num.charAt(i) - '0';
10 digitFrequency[digit]++;
11 }
12
13 // Verify that each position i contains the count of digit i
14 // For example, if digit 0 appears 2 times, position 0 should contain '2'
15 for (int position = 0; position < length; position++) {
16 int expectedCount = num.charAt(position) - '0';
17 int actualCount = digitFrequency[position];
18
19 if (expectedCount != actualCount) {
20 return false;
21 }
22 }
23
24 return true;
25 }
26}
27
1class Solution {
2public:
3 bool digitCount(string num) {
4 // Array to store the frequency count of each digit (0-9)
5 int digitFrequency[10] = {0};
6
7 // Count the occurrence of each digit in the string
8 for (char& currentChar : num) {
9 int digit = currentChar - '0'; // Convert character to integer
10 ++digitFrequency[digit];
11 }
12
13 // Verify if each position i contains the count of digit i in the string
14 for (int i = 0; i < num.size(); ++i) {
15 int expectedCount = num[i] - '0'; // The value at position i
16 int actualCount = digitFrequency[i]; // Actual count of digit i
17
18 if (actualCount != expectedCount) {
19 return false;
20 }
21 }
22
23 return true;
24 }
25};
26
1/**
2 * Checks if a number string is self-describing.
3 * A string is self-describing if digit at index i represents the count of digit i in the string.
4 *
5 * @param num - The input string containing only digits
6 * @returns true if the string is self-describing, false otherwise
7 */
8function digitCount(num: string): boolean {
9 // Initialize an array to count occurrences of each digit (0-9)
10 const digitFrequency: number[] = Array(10).fill(0);
11
12 // Count the frequency of each digit in the input string
13 for (const char of num) {
14 // Convert character to number and increment its count
15 digitFrequency[Number(char)]++;
16 }
17
18 // Verify if each position satisfies the self-describing property
19 for (let index = 0; index < num.length; index++) {
20 // Check if the count of digit 'index' matches the value at position 'index'
21 if (digitFrequency[index] !== Number(num[index])) {
22 return false;
23 }
24 }
25
26 return true;
27}
28
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the string num
. This is because:
- Creating the Counter iterates through all
n
characters once:O(n)
- The
all()
function with the generator expression iterates through alln
positions in the string once:O(n)
- Total:
O(n) + O(n) = O(n)
The space complexity is O(|Σ|)
, where |Σ|
represents the size of the character set (the range of possible digit values), which is 10
for digits 0-9
. This is because:
- The Counter object stores at most
10
different digit counts (for digits0
through9
), regardless of the input string length - Even though we iterate through
n
elements, the Counter can only have at most10
keys - Therefore, the space used by the Counter is bounded by the constant
10
, giving usO(10) = O(|Σ|)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Confusing Position Index with Digit Value
A frequent mistake is mixing up what needs to be counted versus what the expected count should be. Developers often incorrectly check if the digit at position i
appears i
times, rather than checking if digit i
appears num[i]
times.
Incorrect approach:
# WRONG: Checking if num[i] appears i times
return all(digit_frequency[int(num[i])] == i for i in range(len(num)))
Correct approach:
# RIGHT: Checking if digit i appears num[i] times
return all(digit_frequency[i] == int(num[i]) for i in range(len(num)))
Pitfall 2: Not Handling Digits Beyond String Length
When the string length is less than 10, some digits (those greater than or equal to the string length) cannot have position indices in the string. If any of these digits appear in the string, the condition is automatically violated since there's no position to specify their count.
Example: If num = "302"
(length 3), digit 3 appears once but there's no position 3 to specify that it should appear once. This string should return false
.
Solution: The provided code handles this correctly because when we enumerate through positions 0 to n-1, we only check digits that have corresponding positions. However, to be explicit about this edge case:
def digitCount(self, num: str) -> bool:
digit_frequency = Counter(int(digit) for digit in num)
# First check: any digit >= len(num) should not appear
for digit in digit_frequency:
if digit >= len(num) and digit_frequency[digit] > 0:
return False
# Then check the main condition
return all(digit_frequency[i] == int(num[i]) for i in range(len(num)))
Pitfall 3: Forgetting Zero-Count Requirements
When num[i] = '0'
, it means digit i
should not appear anywhere in the string. Developers sometimes forget to verify this "absence" requirement.
Solution: The Counter
object in Python handles this elegantly - accessing a non-existent key returns 0, which correctly validates the zero-count requirement. Just ensure you're comparing with the integer value, not the character:
# Correct: converts '0' to 0 for comparison
digit_frequency[i] == int(num[i])
# Wrong: comparing with character '0'
digit_frequency[i] == num[i]
What are the two properties the problem needs to have for dynamic programming to be applicable? (Select 2)
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!