Files
codetutor/backend/data/questions/check-if-number-has-equal-digit-count-and-digit-value.yaml

195 lines
8.1 KiB
YAML

title: Check if Number Has Equal Digit Count and Digit Value
slug: check-if-number-has-equal-digit-count-and-digit-value
difficulty: easy
leetcode_id: 2283
leetcode_url: https://leetcode.com/problems/check-if-number-has-equal-digit-count-and-digit-value/
categories:
- strings
- hash-tables
patterns:
- prefix-sum
function_signature: "def digit_count(num: str) -> bool:"
test_cases:
visible:
- input: { num: "1210" }
expected: true
- input: { num: "030" }
expected: false
hidden:
- input: { num: "2020" }
expected: true
- input: { num: "0" }
expected: false
- input: { num: "10" }
expected: false
- input: { num: "21200" }
expected: true
- input: { num: "1111" }
expected: false
- input: { num: "2100" }
expected: true
description: |
You are given a **0-indexed** string `num` of length `n` consisting of digits.
Return `true` *if for **every** index* `i` *in the range* `0 <= i < n`*, the digit* `i` *occurs* `num[i]` *times in* `num`*, otherwise return* `false`.
constraints: |
- `n == num.length`
- `1 <= n <= 10`
- `num` consists only of digits
examples:
- input: 'num = "1210"'
output: "true"
explanation: |
num[0] = '1'. The digit 0 occurs once in num.
num[1] = '2'. The digit 1 occurs twice in num.
num[2] = '1'. The digit 2 occurs once in num.
num[3] = '0'. The digit 3 occurs zero times in num.
The condition holds true for every index in "1210", so return true.
- input: 'num = "030"'
output: "false"
explanation: |
num[0] = '0'. The digit 0 should occur zero times, but actually occurs twice in num.
num[1] = '3'. The digit 1 should occur three times, but actually occurs zero times in num.
num[2] = '0'. The digit 2 occurs zero times in num.
The indices 0 and 1 both violate the condition, so return false.
explanation:
intuition: |
Think of this problem as a **self-describing number** puzzle. Each position in the string tells you how many times that position's index should appear as a digit elsewhere in the string.
Imagine the string as a set of rules: position 0 says "the digit 0 must appear exactly `num[0]` times", position 1 says "the digit 1 must appear exactly `num[1]` times", and so on. Your job is to verify that the string follows its own rules.
The key insight is that we need to **count the occurrences** of each digit first, then check if each position's value matches the count for its corresponding index. This is a classic counting problem where we build a frequency map and then validate against it.
approach: |
We solve this using a **Counting Approach**:
**Step 1: Count digit frequencies**
- Create a frequency array or hash map to count how many times each digit (0-9) appears in the string
- Iterate through the string once to populate these counts
&nbsp;
**Step 2: Validate the self-describing property**
- For each index `i` from `0` to `n-1`:
- Get the expected count from `num[i]` (convert character to integer)
- Get the actual count of digit `i` from our frequency map
- If they don't match, return `false`
&nbsp;
**Step 3: Return the result**
- If all positions pass validation, return `true`
&nbsp;
This approach works because we separate the problem into two clear phases: counting and validating. The counting phase gives us the ground truth, and the validation phase checks if the string's claims match reality.
common_pitfalls:
- title: Confusing Index and Value
description: |
The problem has a subtle twist: at index `i`, the *value* `num[i]` tells us how many times the *digit* `i` should appear.
For example, at index 2, if `num[2] = '1'`, this means the digit `2` should appear exactly once in the string — not that the digit `1` should appear twice.
Read carefully: we're checking if digit `i` occurs `num[i]` times.
wrong_approach: "Checking if digit num[i] occurs i times"
correct_approach: "Checking if digit i occurs num[i] times"
- title: Character vs Integer Conversion
description: |
Remember that `num` is a string, so `num[i]` gives a character like `'2'`, not the integer `2`.
You need to convert: `int(num[i])` in Python, or `num[i] - '0'` in languages like C++ or Java.
Forgetting this conversion leads to comparing characters with integers, which will give wrong results or type errors.
wrong_approach: "Comparing num[i] directly with count"
correct_approach: "Convert num[i] to integer before comparison"
- title: Not Handling All Indices
description: |
Since the string has length `n`, we only need to check indices `0` through `n-1`. We only care about digits `0` through `n-1` as well, since larger digits can't be valid indices.
However, digits larger than `n-1` appearing in the string is fine — they just won't be checked as indices. The constraint `n <= 10` ensures all digits 0-9 are potentially valid.
key_takeaways:
- "**Self-describing structures**: Some problems define constraints that reference themselves — break these into counting and validation phases"
- "**Frequency counting pattern**: Building a frequency map first simplifies many validation problems"
- "**Index vs value awareness**: Pay close attention to what the index represents vs what the value represents"
- "**Small constraint optimisation**: With `n <= 10`, even O(n^2) would work, but O(n) is cleaner and teaches better habits"
time_complexity: "O(n). We iterate through the string twice: once to count frequencies, once to validate."
space_complexity: "O(1). We use a fixed-size frequency array of 10 elements (for digits 0-9), regardless of input size."
solutions:
- approach_name: Frequency Counting
is_optimal: true
code: |
def digit_count(num: str) -> bool:
# Count occurrences of each digit (0-9)
freq = [0] * 10
for char in num:
freq[int(char)] += 1
# Check if each index i has digit i appearing num[i] times
for i in range(len(num)):
expected = int(num[i]) # How many times digit i should appear
actual = freq[i] # How many times digit i actually appears
if expected != actual:
return False
return True
explanation: |
**Time Complexity:** O(n) — Two passes through the string of length n.
**Space Complexity:** O(1) — Fixed array of 10 integers.
We first count all digit occurrences, then verify each position's claim. The fixed-size frequency array makes this space-efficient.
- approach_name: Counter with Pythonic Check
is_optimal: true
code: |
from collections import Counter
def digit_count(num: str) -> bool:
# Count all digit occurrences
count = Counter(num)
# Check each index: digit i should occur num[i] times
for i, char in enumerate(num):
expected = int(char)
actual = count.get(str(i), 0) # Get count of digit i (as string)
if expected != actual:
return False
return True
explanation: |
**Time Complexity:** O(n) — Counter creation and validation loop.
**Space Complexity:** O(k) — Where k is the number of unique digits (at most 10).
This approach uses Python's Counter for cleaner counting. Note that we look up `str(i)` since Counter keys are characters, not integers.
- approach_name: One-Liner (Pythonic)
is_optimal: true
code: |
from collections import Counter
def digit_count(num: str) -> bool:
count = Counter(num)
return all(count.get(str(i), 0) == int(c) for i, c in enumerate(num))
explanation: |
**Time Complexity:** O(n) — Single pass with generator expression.
**Space Complexity:** O(k) — Counter storage for unique digits.
A concise one-liner using `all()` with a generator. For each position, we check if the count of that index-as-digit matches the expected value. Elegant but less readable for beginners.