diff --git a/solution/0300-0399/0357.Count Numbers with Unique Digits/README.md b/solution/0300-0399/0357.Count Numbers with Unique Digits/README.md index 438b25f5fc0fa..bb61fc31744b8 100644 --- a/solution/0300-0399/0357.Count Numbers with Unique Digits/README.md +++ b/solution/0300-0399/0357.Count Numbers with Unique Digits/README.md @@ -29,7 +29,7 @@ tags:
 输入:n = 2
 输出:91
-解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。 
+解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。
 

示例 2:

@@ -55,101 +55,7 @@ tags: -### 方法一:排列组合 - -当 $n=0$ 时,有 $0\le x \lt 1$,只有 $1$ 个数字,即 $0$。 - -当 $n=1$ 时,有 $0\le x \lt 10$,有 $10$ 个数字,即 $0,1,2,3,4,5,6,7,8,9$。 - -当 $n=2$ 时,有 $0\le x \lt 100$,那么 $x$ 的选择可以由两部分组成:只有一位数的数字和有两位数的数字。对于只有一位数的情况,可以由上述的边界情况计算;对于有两位数的情况,由于第一位数字不能为 $0$,所以第一位数字有 $9$ 种选择,第二位数字有 $9$ 种选择,所以有 $9 \times 9$ 种选择,即 $81$ 种选择。 - -更一般的情况,含有 $n$ 位数且各位数字都不同的数字 $x$ 的个数为 $9 \times A_{9}^{n-1}$。再加上含有小于 $n$ 位数且各位数字都不同的数字 $x$ 的个数,即为答案。 - -时间复杂度 $O(n)$。 - - - -#### Python3 - -```python -class Solution: - def countNumbersWithUniqueDigits(self, n: int) -> int: - if n == 0: - return 1 - if n == 1: - return 10 - ans, cur = 10, 9 - for i in range(n - 1): - cur *= 9 - i - ans += cur - return ans -``` - -#### Java - -```java -class Solution { - public int countNumbersWithUniqueDigits(int n) { - if (n == 0) { - return 1; - } - if (n == 1) { - return 10; - } - int ans = 10; - for (int i = 0, cur = 9; i < n - 1; ++i) { - cur *= (9 - i); - ans += cur; - } - return ans; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int countNumbersWithUniqueDigits(int n) { - if (n == 0) return 1; - if (n == 1) return 10; - int ans = 10; - for (int i = 0, cur = 9; i < n - 1; ++i) { - cur *= (9 - i); - ans += cur; - } - return ans; - } -}; -``` - -#### Go - -```go -func countNumbersWithUniqueDigits(n int) int { - if n == 0 { - return 1 - } - if n == 1 { - return 10 - } - ans := 10 - for i, cur := 0, 9; i < n-1; i++ { - cur *= (9 - i) - ans += cur - } - return ans -} -``` - - - - - - - -### 方法二:状态压缩 + 数位 DP +### 方法一:状态压缩 + 数位 DP 这道题实际上是求在给定区间 $[l,..r]$ 中,满足条件的数的个数。条件与数的大小无关,而只与数的组成有关,因此可以使用数位 DP 的思想求解。数位 DP 中,数的大小对复杂度的影响很小。 @@ -163,17 +69,29 @@ $$ 这里我们用记忆化搜索来实现数位 DP。从起点向下搜索,到最底层得到方案数,一层层向上返回答案并累加,最后从搜索起点得到最终的答案。 -我们根据题目信息,设计函数 $dfs()$,对于本题,我们定义 $dfs(pos, mask, lead)$,答案为 $dfs(len, 0, true)$。 +我们根据题目信息,设计一个函数 $\textit{dfs}(i, \textit{mask}, \textit{lead})$,其中: + +- 数字 $i$ 表示当前搜索到的位置,我们从高位开始搜索,即 $i = 0$ 表示最高位。 +- 数字 $\textit{mask}$ 表示当前数字的状态,即 $\textit{mask}$ 的第 $j$ 位为 $1$ 表示数字 $j$ 已经被使用过。 +- 布尔值 $\textit{lead}$ 表示当前是否只包含前导 $0$。 -其中: +函数的执行过程如下: -- `pos` 表示数字的位数,从末位或者第一位开始,一般根据题目的数字构造性质来选择顺序。对于本题,我们选择从高位开始,因此,`pos` 的初始值为 `len`; -- `mask` 表示当前数字选取了哪些数字(状态压缩); -- `lead` 表示当前数字是否含有前导零; +如果 $i$ 超过了数字 $n$ 的长度,即 $i \lt 0$,说明搜索结束,直接返回 $1$。 + +否则,我们从 $0$ 到 $9$ 枚举位置 $i$ 的数字 $j$,对于每一个 $j$: + +- 如果 $\textit{mask}$ 的第 $j$ 位为 $1$,说明数字 $j$ 已经被使用过,直接跳过。 +- 如果 $\textit{lead}$ 为真且 $j = 0$,说明当前数字只包含前导 $0$,递归到下一层时,此时 $\textit{lead}$ 仍为真。 +- 否则,我们递归到下一层,更新 $\textit{mask}$ 的第 $j$ 位为 $1$,并将 $\textit{lead}$ 更新为假。 + +最后,我们将所有递归到下一层的结果累加,即为答案。 + +答案为 $\textit{dfs}(n - 1, 0, \textit{True})$。 关于函数的实现细节,可以参考下面的代码。 -时间复杂度 $O(n)$。 +时间复杂度 $O(n \times 2^D \times D)$,空间复杂度 $O(n \times 2^D)$。其中 $n$ 为数字 $n$ 的长度,而 $D = 10$。 相似题目: @@ -192,55 +110,53 @@ $$ class Solution: def countNumbersWithUniqueDigits(self, n: int) -> int: @cache - def dfs(pos, mask, lead): - if pos <= 0: + def dfs(i: int, mask: int, lead: bool) -> int: + if i < 0: return 1 ans = 0 - for i in range(10): - if (mask >> i) & 1: + for j in range(10): + if mask >> j & 1: continue - if i == 0 and lead: - ans += dfs(pos - 1, mask, lead) + if lead and j == 0: + ans += dfs(i - 1, mask, True) else: - ans += dfs(pos - 1, mask | (1 << i), False) + ans += dfs(i - 1, mask | 1 << j, False) return ans - return dfs(n, 0, True) + return dfs(n - 1, 0, True) ``` #### Java ```java class Solution { - private int[][] dp = new int[10][1 << 11]; + private Integer[][] f; public int countNumbersWithUniqueDigits(int n) { - for (var e : dp) { - Arrays.fill(e, -1); - } - return dfs(n, 0, true); + f = new Integer[n][1 << 10]; + return dfs(n - 1, 0, true); } - private int dfs(int pos, int mask, boolean lead) { - if (pos <= 0) { + private int dfs(int i, int mask, boolean lead) { + if (i < 0) { return 1; } - if (!lead && dp[pos][mask] != -1) { - return dp[pos][mask]; + if (!lead && f[i][mask] != null) { + return f[i][mask]; } int ans = 0; - for (int i = 0; i < 10; ++i) { - if (((mask >> i) & 1) == 1) { + for (int j = 0; j <= 9; ++j) { + if ((mask >> j & 1) == 1) { continue; } - if (i == 0 && lead) { - ans += dfs(pos - 1, mask, lead); + if (lead && j == 0) { + ans += dfs(i - 1, mask, true); } else { - ans += dfs(pos - 1, mask | (1 << i), false); + ans += dfs(i - 1, mask | 1 << j, false); } } if (!lead) { - dp[pos][mask] = ans; + f[i][mask] = ans; } return ans; } @@ -252,33 +168,33 @@ class Solution { ```cpp class Solution { public: - int dp[10][1 << 11]; - int countNumbersWithUniqueDigits(int n) { - memset(dp, -1, sizeof dp); - return dfs(n, 0, true); - } - - int dfs(int pos, int mask, bool lead) { - if (pos <= 0) { - return 1; - } - if (!lead && dp[pos][mask] != -1) { - return dp[pos][mask]; - } - int ans = 0; - for (int i = 0; i < 10; ++i) { - if ((mask >> i) & 1) continue; - if (i == 0 && lead) { - ans += dfs(pos - 1, mask, lead); - } else { - ans += dfs(pos - 1, mask | 1 << i, false); + 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) { - dp[pos][mask] = ans; - } - return ans; + 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); } }; ``` @@ -287,39 +203,69 @@ public: ```go func countNumbersWithUniqueDigits(n int) int { - dp := make([][]int, 10) - for i := range dp { - dp[i] = make([]int, 1<<11) - for j := range dp[i] { - dp[i][j] = -1 + f := make([][1 << 10]int, n) + for i := range f { + for j := range f[i] { + f[i][j] = -1 } } - var dfs func(int, int, bool) int - dfs = func(pos, mask int, lead bool) int { - if pos <= 0 { + var dfs func(i, mask int, lead bool) int + dfs = func(i, mask int, lead bool) int { + if i < 0 { return 1 } - if !lead && dp[pos][mask] != -1 { - return dp[pos][mask] + if !lead && f[i][mask] != -1 { + return f[i][mask] } ans := 0 - for i := 0; i < 10; i++ { - if ((mask >> i) & 1) == 1 { + for j := 0; j < 10; j++ { + if mask>>j&1 == 1 { continue } - if i == 0 && lead { - ans += dfs(pos-1, mask, lead) + if lead && j == 0 { + ans += dfs(i-1, mask, true) } else { - ans += dfs(pos-1, mask|1< 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); } ``` diff --git a/solution/0300-0399/0357.Count Numbers with Unique Digits/README_EN.md b/solution/0300-0399/0357.Count Numbers with Unique Digits/README_EN.md index 20f6e0226e6e3..05df4166af3c1 100644 --- a/solution/0300-0399/0357.Count Numbers with Unique Digits/README_EN.md +++ b/solution/0300-0399/0357.Count Numbers with Unique Digits/README_EN.md @@ -49,91 +49,50 @@ tags: -### Solution 1 +### Solution 1: State Compression + Digit DP - +This problem essentially asks for the number of numbers in the given range $[l, ..r]$ that satisfy certain conditions. The conditions are related to the composition of the numbers rather than their size, so we can use the concept of Digit DP to solve it. In Digit DP, the size of the number has little impact on the complexity. -#### Python3 +For the range $[l, ..r]$ problem, we generally convert it to the problem of $[1, ..r]$ and then subtract the result of $[1, ..l - 1]$, i.e.: -```python -class Solution: - def countNumbersWithUniqueDigits(self, n: int) -> int: - if n == 0: - return 1 - if n == 1: - return 10 - ans, cur = 10, 9 - for i in range(n - 1): - cur *= 9 - i - ans += cur - return ans -``` +$$ +ans = \sum_{i=1}^{r} ans_i - \sum_{i=1}^{l-1} ans_i +$$ -#### Java +However, for this problem, we only need to find the value for the range $[1, ..10^n-1]$. -```java -class Solution { - public int countNumbersWithUniqueDigits(int n) { - if (n == 0) { - return 1; - } - if (n == 1) { - return 10; - } - int ans = 10; - for (int i = 0, cur = 9; i < n - 1; ++i) { - cur *= (9 - i); - ans += cur; - } - return ans; - } -} -``` +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. -#### C++ +Based on the problem information, we design a function $\textit{dfs}(i, \textit{mask}, \textit{lead})$, where: -```cpp -class Solution { -public: - int countNumbersWithUniqueDigits(int n) { - if (n == 0) return 1; - if (n == 1) return 10; - int ans = 10; - for (int i = 0, cur = 9; i < n - 1; ++i) { - cur *= (9 - i); - ans += cur; - } - return ans; - } -}; -``` +- 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. -#### Go +The function executes as follows: -```go -func countNumbersWithUniqueDigits(n int) int { - if n == 0 { - return 1 - } - if n == 1 { - return 10 - } - ans := 10 - for i, cur := 0, 9; i < n-1; i++ { - cur *= (9 - i) - ans += cur - } - return ans -} -``` +If $i$ exceeds the length of the number $n$, i.e., $i < 0$, it means the search is over, directly return $1$. - +Otherwise, we enumerate the digits $j$ from $0$ to $9$ for the position $i$. For each $j$: - +- 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 $\textit{dfs}(n - 1, 0, \textit{True})$. + +The time complexity is $O(n \times 2^D \times D)$, and the space complexity is $O(n \times 2^D)$. Here, $n$ is the length of the number $n$, and $D = 10$. -### Solution 2 +Similar Problems: + +- [233. Number of Digit One](https://github.com/doocs/leetcode/blob/main/solution/0200-0299/0233.Number%20of%20Digit%20One/README_EN.md) +- [600. Non-negative Integers without Consecutive Ones](https://github.com/doocs/leetcode/blob/main/solution/0600-0699/0600.Non-negative%20Integers%20without%20Consecutive%20Ones/README_EN.md) +- [788. Rotated Digits](https://github.com/doocs/leetcode/blob/main/solution/0700-0799/0788.Rotated%20Digits/README_EN.md) +- [902. Numbers At Most N Given Digit Set](https://github.com/doocs/leetcode/blob/main/solution/0900-0999/0902.Numbers%20At%20Most%20N%20Given%20Digit%20Set/README_EN.md) +- [1012. Numbers with Repeated Digits](https://github.com/doocs/leetcode/blob/main/solution/1000-1099/1012.Numbers%20With%20Repeated%20Digits/README_EN.md) +- [2376. Count Special Integers](https://github.com/doocs/leetcode/blob/main/solution/2300-2399/2376.Count%20Special%20Integers/README_EN.md) @@ -143,55 +102,53 @@ func countNumbersWithUniqueDigits(n int) int { class Solution: def countNumbersWithUniqueDigits(self, n: int) -> int: @cache - def dfs(pos, mask, lead): - if pos <= 0: + def dfs(i: int, mask: int, lead: bool) -> int: + if i < 0: return 1 ans = 0 - for i in range(10): - if (mask >> i) & 1: + for j in range(10): + if mask >> j & 1: continue - if i == 0 and lead: - ans += dfs(pos - 1, mask, lead) + if lead and j == 0: + ans += dfs(i - 1, mask, True) else: - ans += dfs(pos - 1, mask | (1 << i), False) + ans += dfs(i - 1, mask | 1 << j, False) return ans - return dfs(n, 0, True) + return dfs(n - 1, 0, True) ``` #### Java ```java class Solution { - private int[][] dp = new int[10][1 << 11]; + private Integer[][] f; public int countNumbersWithUniqueDigits(int n) { - for (var e : dp) { - Arrays.fill(e, -1); - } - return dfs(n, 0, true); + f = new Integer[n][1 << 10]; + return dfs(n - 1, 0, true); } - private int dfs(int pos, int mask, boolean lead) { - if (pos <= 0) { + private int dfs(int i, int mask, boolean lead) { + if (i < 0) { return 1; } - if (!lead && dp[pos][mask] != -1) { - return dp[pos][mask]; + if (!lead && f[i][mask] != null) { + return f[i][mask]; } int ans = 0; - for (int i = 0; i < 10; ++i) { - if (((mask >> i) & 1) == 1) { + for (int j = 0; j <= 9; ++j) { + if ((mask >> j & 1) == 1) { continue; } - if (i == 0 && lead) { - ans += dfs(pos - 1, mask, lead); + if (lead && j == 0) { + ans += dfs(i - 1, mask, true); } else { - ans += dfs(pos - 1, mask | (1 << i), false); + ans += dfs(i - 1, mask | 1 << j, false); } } if (!lead) { - dp[pos][mask] = ans; + f[i][mask] = ans; } return ans; } @@ -203,33 +160,33 @@ class Solution { ```cpp class Solution { public: - int dp[10][1 << 11]; - int countNumbersWithUniqueDigits(int n) { - memset(dp, -1, sizeof dp); - return dfs(n, 0, true); - } - - int dfs(int pos, int mask, bool lead) { - if (pos <= 0) { - return 1; - } - if (!lead && dp[pos][mask] != -1) { - return dp[pos][mask]; - } - int ans = 0; - for (int i = 0; i < 10; ++i) { - if ((mask >> i) & 1) continue; - if (i == 0 && lead) { - ans += dfs(pos - 1, mask, lead); - } else { - ans += dfs(pos - 1, mask | 1 << i, false); + 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) { - dp[pos][mask] = ans; - } - return ans; + 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); } }; ``` @@ -238,39 +195,69 @@ public: ```go func countNumbersWithUniqueDigits(n int) int { - dp := make([][]int, 10) - for i := range dp { - dp[i] = make([]int, 1<<11) - for j := range dp[i] { - dp[i][j] = -1 + f := make([][1 << 10]int, n) + for i := range f { + for j := range f[i] { + f[i][j] = -1 } } - var dfs func(int, int, bool) int - dfs = func(pos, mask int, lead bool) int { - if pos <= 0 { + var dfs func(i, mask int, lead bool) int + dfs = func(i, mask int, lead bool) int { + if i < 0 { return 1 } - if !lead && dp[pos][mask] != -1 { - return dp[pos][mask] + if !lead && f[i][mask] != -1 { + return f[i][mask] } ans := 0 - for i := 0; i < 10; i++ { - if ((mask >> i) & 1) == 1 { + for j := 0; j < 10; j++ { + if mask>>j&1 == 1 { continue } - if i == 0 && lead { - ans += dfs(pos-1, mask, lead) + if lead && j == 0 { + ans += dfs(i-1, mask, true) } else { - ans += dfs(pos-1, mask|1< 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); } ``` diff --git a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.cpp b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.cpp index b0a07584d382c..461100326c921 100644 --- a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.cpp +++ b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.cpp @@ -1,13 +1,31 @@ class Solution { public: int countNumbersWithUniqueDigits(int n) { - if (n == 0) return 1; - if (n == 1) return 10; - int ans = 10; - for (int i = 0, cur = 9; i < n - 1; ++i) { - cur *= (9 - i); - ans += cur; - } - return ans; + 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); } -}; \ No newline at end of file +}; diff --git a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.go b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.go index 238b18dabf824..26641c292940e 100644 --- a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.go +++ b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.go @@ -1,14 +1,33 @@ func countNumbersWithUniqueDigits(n int) int { - if n == 0 { - return 1 + f := make([][1 << 10]int, n) + for i := range f { + for j := range f[i] { + f[i][j] = -1 + } } - if n == 1 { - return 10 + 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 & 1) == 1) { + continue; + } + if (lead && j == 0) { + ans += dfs(i - 1, mask, true); + } else { + ans += dfs(i - 1, mask | 1 << j, false); + } } - int ans = 10; - for (int i = 0, cur = 9; i < n - 1; ++i) { - cur *= (9 - i); - ans += cur; + if (!lead) { + f[i][mask] = ans; } return ans; } -} \ No newline at end of file +} diff --git a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.py b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.py index b2cfdae7f9b28..5ccfed0c621a9 100644 --- a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.py +++ b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.py @@ -1,11 +1,17 @@ class Solution: def countNumbersWithUniqueDigits(self, n: int) -> int: - if n == 0: - return 1 - if n == 1: - return 10 - ans, cur = 10, 9 - for i in range(n - 1): - cur *= 9 - i - ans += cur - return ans + @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) diff --git a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.ts b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.ts new file mode 100644 index 0000000000000..8348b2fa60e99 --- /dev/null +++ b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution.ts @@ -0,0 +1,27 @@ +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); +} diff --git a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution2.cpp b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution2.cpp deleted file mode 100644 index 1b5eec267f1e1..0000000000000 --- a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution2.cpp +++ /dev/null @@ -1,31 +0,0 @@ -class Solution { -public: - int dp[10][1 << 11]; - - int countNumbersWithUniqueDigits(int n) { - memset(dp, -1, sizeof dp); - return dfs(n, 0, true); - } - - int dfs(int pos, int mask, bool lead) { - if (pos <= 0) { - return 1; - } - if (!lead && dp[pos][mask] != -1) { - return dp[pos][mask]; - } - int ans = 0; - for (int i = 0; i < 10; ++i) { - if ((mask >> i) & 1) continue; - if (i == 0 && lead) { - ans += dfs(pos - 1, mask, lead); - } else { - ans += dfs(pos - 1, mask | 1 << i, false); - } - } - if (!lead) { - dp[pos][mask] = ans; - } - return ans; - } -}; \ No newline at end of file diff --git a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution2.go b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution2.go deleted file mode 100644 index 106797551d9e4..0000000000000 --- a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution2.go +++ /dev/null @@ -1,35 +0,0 @@ -func countNumbersWithUniqueDigits(n int) int { - dp := make([][]int, 10) - for i := range dp { - dp[i] = make([]int, 1<<11) - for j := range dp[i] { - dp[i][j] = -1 - } - } - var dfs func(int, int, bool) int - dfs = func(pos, mask int, lead bool) int { - if pos <= 0 { - return 1 - } - if !lead && dp[pos][mask] != -1 { - return dp[pos][mask] - } - ans := 0 - for i := 0; i < 10; i++ { - if ((mask >> i) & 1) == 1 { - continue - } - if i == 0 && lead { - ans += dfs(pos-1, mask, lead) - } else { - ans += dfs(pos-1, mask|1<> i) & 1) == 1) { - continue; - } - if (i == 0 && lead) { - ans += dfs(pos - 1, mask, lead); - } else { - ans += dfs(pos - 1, mask | (1 << i), false); - } - } - if (!lead) { - dp[pos][mask] = ans; - } - return ans; - } -} \ No newline at end of file diff --git a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution2.py b/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution2.py deleted file mode 100644 index 3f88638764666..0000000000000 --- a/solution/0300-0399/0357.Count Numbers with Unique Digits/Solution2.py +++ /dev/null @@ -1,17 +0,0 @@ -class Solution: - def countNumbersWithUniqueDigits(self, n: int) -> int: - @cache - def dfs(pos, mask, lead): - if pos <= 0: - return 1 - ans = 0 - for i in range(10): - if (mask >> i) & 1: - continue - if i == 0 and lead: - ans += dfs(pos - 1, mask, lead) - else: - ans += dfs(pos - 1, mask | (1 << i), False) - return ans - - return dfs(n, 0, True)