Python 0357.py
class Solution:
def countNumbersWithUniqueDigits(self, n: int) -> int:
# brute-force shows that for n = 0, 1, 2, 3
# we get 1, 10, 91, 739
# => OEIS sequence A344389, which is based on A073531
def A073531(n):
return 9 * factorial(9) // factorial(10 - n)
result = 1
for i in range(1, n+1):
result += A073531(i)
return result
Difficulty
and has an acceptance rate of about 56% (300k+ submissions).
Typical patterns to solve this problem:
- Backtracking
- Dynamic Programming
- Math
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 computes the total count of non-negative integers whose decimal representation contains no repeated digits, for all lengths from 0 up to a given n. The algorithm builds the answer incrementally: it starts with the base case for length 0 and then adds the contribution of each length 1…n using a closed-form combinatorial helper.
Key Steps
Definition of the combinatorial helper
def A073531(n):
return 9 * factorial(9) // factorial(10 - n)
This inner function implements the formula for the number of n-digit numbers with all distinct digits, assuming the most significant digit cannot be zero. The expression 9 * factorial(9) // factorial(10 - n) directly evaluates the product
9 × 9 × 8 × 7 × … × (10-n)
by leveraging the factorial function, thereby avoiding explicit loops for the multiplication chain.
Initialization of the accumulator
result = 1
The variable result is seeded with 1, which accounts for the single valid number of length 0 - the integer 0 itself. This establishes the correct base for the cumulative sum.
Iterative accumulation over lengths
for i in range(1, n+1):
result += A073531(i)
The loop iterates from 1 through n, invoking the combinatorial helper for each length i and adding its return value to result. Because the helper already returns the exact count for the current length, the loop simply aggregates the totals for all lengths up to n.
Final return
return result
After the loop finishes, result holds the sum of counts for lengths 0…n, which is the required answer.
Edge Cases Handled
When n equals 0, the for loop’s range becomes empty, so the body is never executed. The function therefore returns the initial value of result, which is 1 - correctly representing the sole number 0 that satisfies the uniqueness condition for length 0.
The helper A073531 is defined for n values from 1 up to 9. For n = 1 the expression evaluates to 9 * factorial(9) // factorial(9), yielding 9, which together with the base case gives the expected total of 10 (the digits 0-9). For n = 9 the denominator becomes factorial(1), and the formula computes the full set of 9-digit numbers with distinct digits. The implementation therefore gracefully covers the full range of meaningful inputs where distinct-digit numbers exist.
Performance Optimizations
The use of the factorial-based closed form in A073531 eliminates the need for nested loops or repeated multiplication for each digit position. By calling factorial from the standard library, the code benefits from a highly optimized C implementation, which computes the factorial values quickly and with minimal overhead.
The outer loop runs exactly n times, and each iteration performs only a constant-time arithmetic operation (a function call and an addition). This linear progression is optimal for the problem’s domain, where n never exceeds 9 in practice, so the total work remains trivial even for the maximum input.
Because all intermediate results are integers and Python’s arbitrary-precision arithmetic handles them without overflow, the algorithm avoids any extra checks or conversions, keeping the execution path tight and efficient.
ELI5 - Simplified Explanation
Imagine having a giant box of number blocks, and the goal is to count how many special numbers can be made using those blocks. Every block has a number from zero to nine, but there is a rule that every block in a number must be different.
The code starts by knowing that the number zero is a special case that counts as one. Then, it goes on a little journey to check numbers with one digit, then two, then three, and so on, depending on how big the number chosen is.
Inside the loop, the code uses a helper tool that figures out how many ways different digits can be placed in a row without ever repeating the same digit. For each size, the code does a quick calculation of all those possible unique combinations. It keeps adding these counts to a growing pile until it finishes checking all the sizes asked for. By the end, the growing pile holds the total count of every single number that does not have any repeating digits.
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 | TS | |||||
| LeetcodeHelp | C++ | Python | Java | |||||||
| Progiez | C++ | Python | Java | |||||||
| github | black-shadows | C++ | ||||||||
| charles-wangkai | Java | |||||||||
| chenyanzhe | C++ | |||||||||
| everthis | JS | |||||||||
| halfrost | Go | |||||||||
| haoel | C++ | |||||||||
| JoshCrozier | JS | |||||||||
| linouk23 | C++ | |||||||||
| lkwq007 | Python | |||||||||
| lzl124631x | C++ | |||||||||
| ruoru | Rust | |||||||||
| suxrobGM | C# | |||||||||
| trung-hn | Python | |||||||||
| varunu28 | Java | |||||||||
| wisdompeak | C++ | |||||||||
| yuanliu666 | Kotlin | |||||||||
| zfang399 | C++ | |||||||||
| AlgoMonster | C++, Python, Java, TypeScript | |||||||||
| WalkCCC | C++, Python, Java | |||||||||
| leetcode.ca | C++, Go, Java, Python, TypeScript | |||||||||
| LeetcodeHelp | C++, Java, Python | |||||||||
| Progiez | C++, Java, Python | |||||||||
| black-shadows | C++, C++ | |||||||||
| charles-wangkai | Java | |||||||||
| chenyanzhe | C++ | |||||||||
| everthis | JavaScript | |||||||||
| halfrost | Go | |||||||||
| haoel | C++ | |||||||||
| JoshCrozier | JavaScript | |||||||||
| linouk23 | C++ | |||||||||
| lkwq007 | Python | |||||||||
| lzl124631x | C++ | |||||||||
| ruoru | Rust | |||||||||
| suxrobGM | C# | |||||||||
| trung-hn | Python | |||||||||
| varunu28 | Java | |||||||||
| wisdompeak | C++ | |||||||||
| yuanliu666 | Kotlin | |||||||||
| zfang399 | C++ |
Videos
Similar Problems
- problem 3032: Count Numbers With Unique Digits II
Solved On The Same Day
- problem 415: Add Strings
- problem 463: Island Perimeter
- problem 541: Reverse String II
- problem 1211: Queries Quality and Percentage
- problem 1251: Average Selling Price
- problem 1280: Students and Examinations
- problem 1327: List the Products Ordered in a Period
- problem 1378: Replace Employee ID With The Unique Identifier
- problem 1407: Top Travellers
- problem 1484: Group Sold Products By The Date
- problem 1517: Find Users With Valid E-Mails
- problem 1527: Patients With a Condition
- problem 1581: Customer Who Visited but Did Not Make Any Transactions
- problem 1587: Bank Account Summary II
- problem 1633: Percentage of Users Attended a Contest
- problem 1661: Average Time of Process per Machine
- problem 1667: Fix Names in a Table
- problem 1683: Invalid Tweets
- problem 1693: Daily Leads and Partners
- problem 1729: Find Followers Count
- problem 1731: The Number of Employees Which Report to Each Employee
- problem 1741: Find Total Time Spent by Each Employee
- problem 1757: Recyclable and Low Fat Products
- problem 1789: Primary Department for Each Employee
- problem 1795: Rearrange Products Table
- problem 1873: Calculate Special Bonus
- problem 1890: The Latest Login in 2020
- problem 1965: Employees With Missing Information
- problem 1978: Employees Whose Manager Left the Company
- problem 2356: Number of Unique Subjects Taught by Each Teacher
- problem 166: Fraction to Recurring Decimal
- problem 223: Rectangle Area
- problem 240: Search a 2D Matrix II
- problem 318: Maximum Product of Word Lengths
- problem 394: Decode String
- problem 1158: Market Analysis I
- problem 1341: Movie Rating
- problem 1492: The kth Factor of n
- problem 1498: Number of Subsequences That Satisfy the Given Sum Condition
- problem 1907: Count Salary Categories
- problem 1934: Confirmation Rate
- problem 2405: Optimal Partition of String
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