comments | difficulty | edit_url | tags | |||
---|---|---|---|---|---|---|
true |
Medium |
|
Given an integer n
, return the count of all numbers with unique digits, x
, where 0 <= x < 10n
.
Example 1:
Input: n = 2 Output: 91 Explanation: The answer should be the total numbers in the range of 0 ≤ x < 100, excluding 11,22,33,44,55,66,77,88,99
Example 2:
Input: n = 0 Output: 1
Constraints:
0 <= n <= 8
This problem essentially asks for the number of numbers in the given range
For the range
However, for this problem, we only need to find the value for the range
Here, we use memoized search to implement Digit DP. We search from the starting point downwards, and at the lowest level, we get the number of solutions. We then return the answers layer by layer upwards, and finally get the final answer from the starting point of the search.
Based on the problem information, we design a function
- The digit
$i$ represents the current position being searched, starting from the highest digit, i.e.,$i = 0$ represents the highest digit. - The digit
$\textit{mask}$ represents the current state of the number, i.e., the$j$ -th bit of$\textit{mask}$ being$1$ indicates that the digit$j$ has been used. - The boolean
$\textit{lead}$ indicates whether the current number only contains leading $0$s.
The function executes as follows:
If
Otherwise, we enumerate the digits
- If the
$j$ -th bit of$\textit{mask}$ is$1$ , it means the digit$j$ has been used, so we skip it. - If
$\textit{lead}$ is true and$j = 0$ , it means the current number only contains leading $0$s. When we recurse to the next level,$\textit{lead}$ remains true. - Otherwise, we recurse to the next level, update the
$j$ -th bit of$\textit{mask}$ to$1$ , and set$\textit{lead}$ to false.
Finally, we sum all the results from the recursive calls to the next level, which is the answer.
The answer is
The time complexity is
Similar Problems:
- 233. Number of Digit One
- 600. Non-negative Integers without Consecutive Ones
- 788. Rotated Digits
- 902. Numbers At Most N Given Digit Set
- 1012. Numbers with Repeated Digits
- 2376. Count Special Integers
class Solution:
def countNumbersWithUniqueDigits(self, n: int) -> int:
@cache
def dfs(i: int, mask: int, lead: bool) -> int:
if i < 0:
return 1
ans = 0
for j in range(10):
if mask >> j & 1:
continue
if lead and j == 0:
ans += dfs(i - 1, mask, True)
else:
ans += dfs(i - 1, mask | 1 << j, False)
return ans
return dfs(n - 1, 0, True)
class Solution {
private Integer[][] f;
public int countNumbersWithUniqueDigits(int n) {
f = new Integer[n][1 << 10];
return dfs(n - 1, 0, true);
}
private int dfs(int i, int mask, boolean lead) {
if (i < 0) {
return 1;
}
if (!lead && f[i][mask] != null) {
return f[i][mask];
}
int ans = 0;
for (int j = 0; j <= 9; ++j) {
if ((mask >> j & 1) == 1) {
continue;
}
if (lead && j == 0) {
ans += dfs(i - 1, mask, true);
} else {
ans += dfs(i - 1, mask | 1 << j, false);
}
}
if (!lead) {
f[i][mask] = ans;
}
return ans;
}
}
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
int f[n + 1][1 << 10];
memset(f, -1, sizeof(f));
auto dfs = [&](auto&& dfs, int i, int mask, bool lead) -> int {
if (i < 0) {
return 1;
}
if (!lead && f[i][mask] != -1) {
return f[i][mask];
}
int ans = 0;
for (int j = 0; j <= 9; ++j) {
if (mask >> j & 1) {
continue;
}
if (lead && j == 0) {
ans += dfs(dfs, i - 1, mask, true);
} else {
ans += dfs(dfs, i - 1, mask | 1 << i, false);
}
}
if (!lead) {
f[i][mask] = ans;
}
return ans;
};
return dfs(dfs, n - 1, 0, true);
}
};
func countNumbersWithUniqueDigits(n int) int {
f := make([][1 << 10]int, n)
for i := range f {
for j := range f[i] {
f[i][j] = -1
}
}
var dfs func(i, mask int, lead bool) int
dfs = func(i, mask int, lead bool) int {
if i < 0 {
return 1
}
if !lead && f[i][mask] != -1 {
return f[i][mask]
}
ans := 0
for j := 0; j < 10; j++ {
if mask>>j&1 == 1 {
continue
}
if lead && j == 0 {
ans += dfs(i-1, mask, true)
} else {
ans += dfs(i-1, mask|1<<j, false)
}
}
if !lead {
f[i][mask] = ans
}
return ans
}
return dfs(n-1, 0, true)
}
function countNumbersWithUniqueDigits(n: number): number {
const f: number[][] = Array.from({ length: n }, () => Array(1 << 10).fill(-1));
const dfs = (i: number, mask: number, lead: boolean): number => {
if (i < 0) {
return 1;
}
if (!lead && f[i][mask] !== -1) {
return f[i][mask];
}
let ans = 0;
for (let j = 0; j < 10; ++j) {
if ((mask >> j) & 1) {
continue;
}
if (lead && j === 0) {
ans += dfs(i - 1, mask, true);
} else {
ans += dfs(i - 1, mask | (1 << j), false);
}
}
if (!lead) {
f[i][mask] = ans;
}
return ans;
};
return dfs(n - 1, 0, true);
}