2929<pre >
3030<strong >输入:</strong >n = 2
3131<strong >输出:</strong >91
32- <strong >解释:</strong >答案应为除去 <code >11、22、33、44、55、66、77、88、99 </code >外,在 0 ≤ x < ; 100 范围内的所有数字。
32+ <strong >解释:</strong >答案应为除去 <code >11、22、33、44、55、66、77、88、99 </code >外,在 0 ≤ x < ; 100 范围内的所有数字。
3333</pre >
3434
3535<p ><strong >示例 2:</strong ></p >
@@ -55,101 +55,7 @@ tags:
5555
5656<!-- solution:start -->
5757
58- ### 方法一:排列组合
59-
60- 当 $n=0$ 时,有 $0\le x \lt 1$,只有 $1$ 个数字,即 $0$。
61-
62- 当 $n=1$ 时,有 $0\le x \lt 10$,有 $10$ 个数字,即 $0,1,2,3,4,5,6,7,8,9$。
63-
64- 当 $n=2$ 时,有 $0\le x \lt 100$,那么 $x$ 的选择可以由两部分组成:只有一位数的数字和有两位数的数字。对于只有一位数的情况,可以由上述的边界情况计算;对于有两位数的情况,由于第一位数字不能为 $0$,所以第一位数字有 $9$ 种选择,第二位数字有 $9$ 种选择,所以有 $9 \times 9$ 种选择,即 $81$ 种选择。
65-
66- 更一般的情况,含有 $n$ 位数且各位数字都不同的数字 $x$ 的个数为 $9 \times A_ {9}^{n-1}$。再加上含有小于 $n$ 位数且各位数字都不同的数字 $x$ 的个数,即为答案。
67-
68- 时间复杂度 $O(n)$。
69-
70- <!-- tabs:start -->
71-
72- #### Python3
73-
74- ``` python
75- class Solution :
76- def countNumbersWithUniqueDigits (self , n : int ) -> int :
77- if n == 0 :
78- return 1
79- if n == 1 :
80- return 10
81- ans, cur = 10 , 9
82- for i in range (n - 1 ):
83- cur *= 9 - i
84- ans += cur
85- return ans
86- ```
87-
88- #### Java
89-
90- ``` java
91- class Solution {
92- public int countNumbersWithUniqueDigits (int n ) {
93- if (n == 0 ) {
94- return 1 ;
95- }
96- if (n == 1 ) {
97- return 10 ;
98- }
99- int ans = 10 ;
100- for (int i = 0 , cur = 9 ; i < n - 1 ; ++ i) {
101- cur *= (9 - i);
102- ans += cur;
103- }
104- return ans;
105- }
106- }
107- ```
108-
109- #### C++
110-
111- ``` cpp
112- class Solution {
113- public:
114- int countNumbersWithUniqueDigits(int n) {
115- if (n == 0) return 1;
116- if (n == 1) return 10;
117- int ans = 10;
118- for (int i = 0, cur = 9; i < n - 1; ++i) {
119- cur * = (9 - i);
120- ans += cur;
121- }
122- return ans;
123- }
124- };
125- ```
126-
127- #### Go
128-
129- ```go
130- func countNumbersWithUniqueDigits(n int) int {
131- if n == 0 {
132- return 1
133- }
134- if n == 1 {
135- return 10
136- }
137- ans := 10
138- for i, cur := 0, 9; i < n-1; i++ {
139- cur *= (9 - i)
140- ans += cur
141- }
142- return ans
143- }
144- ```
145-
146- <!-- tabs: end -->
147-
148- <!-- solution: end -->
149-
150- <!-- solution: start -->
151-
152- ### 方法二:状态压缩 + 数位 DP
58+ ### 方法一:状态压缩 + 数位 DP
15359
15460这道题实际上是求在给定区间 $[ l,..r] $ 中,满足条件的数的个数。条件与数的大小无关,而只与数的组成有关,因此可以使用数位 DP 的思想求解。数位 DP 中,数的大小对复杂度的影响很小。
15561
16369
16470这里我们用记忆化搜索来实现数位 DP。从起点向下搜索,到最底层得到方案数,一层层向上返回答案并累加,最后从搜索起点得到最终的答案。
16571
166- 我们根据题目信息,设计函数 $dfs()$,对于本题,我们定义 $dfs(pos, mask, lead)$,答案为 $dfs(len, 0, true)$。
72+ 我们根据题目信息,设计一个函数 $\textit{dfs}(i, \textit{mask}, \textit{lead})$,其中:
73+
74+ - 数字 $i$ 表示当前搜索到的位置,我们从高位开始搜索,即 $i = 0$ 表示最高位。
75+ - 数字 $\textit{mask}$ 表示当前数字的状态,即 $\textit{mask}$ 的第 $j$ 位为 $1$ 表示数字 $j$ 已经被使用过。
76+ - 布尔值 $\textit{lead}$ 表示当前是否只包含前导 $0$。
16777
168- 其中 :
78+ 函数的执行过程如下 :
16979
170- - ` pos ` 表示数字的位数,从末位或者第一位开始,一般根据题目的数字构造性质来选择顺序。对于本题,我们选择从高位开始,因此,` pos ` 的初始值为 ` len ` ;
171- - ` mask ` 表示当前数字选取了哪些数字(状态压缩);
172- - ` lead ` 表示当前数字是否含有前导零;
80+ 如果 $i$ 超过了数字 $n$ 的长度,即 $i \lt 0$,说明搜索结束,直接返回 $1$。
81+
82+ 否则,我们从 $0$ 到 $9$ 枚举位置 $i$ 的数字 $j$,对于每一个 $j$:
83+
84+ - 如果 $\textit{mask}$ 的第 $j$ 位为 $1$,说明数字 $j$ 已经被使用过,直接跳过。
85+ - 如果 $\textit{lead}$ 为真且 $j = 0$,说明当前数字只包含前导 $0$,递归到下一层时,此时 $\textit{lead}$ 仍为真。
86+ - 否则,我们递归到下一层,更新 $\textit{mask}$ 的第 $j$ 位为 $1$,并将 $\textit{lead}$ 更新为假。
87+
88+ 最后,我们将所有递归到下一层的结果累加,即为答案。
89+
90+ 答案为 $\textit{dfs}(n - 1, 0, \textit{True})$。
17391
17492关于函数的实现细节,可以参考下面的代码。
17593
176- 时间复杂度 $O(n) $。
94+ 时间复杂度 $O(n \times 2^D \times D)$,空间复杂度 $O(n \times 2^D)$。其中 $n$ 为数字 $n$ 的长度,而 $D = 10 $。
17795
17896相似题目:
17997
192110class Solution :
193111 def countNumbersWithUniqueDigits (self , n : int ) -> int :
194112 @cache
195- def dfs (pos , mask , lead ) :
196- if pos <= 0 :
113+ def dfs (i : int , mask : int , lead : bool ) -> int :
114+ if i < 0 :
197115 return 1
198116 ans = 0
199- for i in range (10 ):
200- if ( mask >> i) & 1 :
117+ for j in range (10 ):
118+ if mask >> j & 1 :
201119 continue
202- if i == 0 and lead :
203- ans += dfs(pos - 1 , mask, lead )
120+ if lead and j == 0 :
121+ ans += dfs(i - 1 , mask, True )
204122 else :
205- ans += dfs(pos - 1 , mask | ( 1 << i) , False )
123+ ans += dfs(i - 1 , mask | 1 << j , False )
206124 return ans
207125
208- return dfs(n, 0 , True )
126+ return dfs(n - 1 , 0 , True )
209127```
210128
211129#### Java
212130
213131``` java
214132class Solution {
215- private int [][] dp = new int [ 10 ][ 1 << 11 ] ;
133+ private Integer [][] f ;
216134
217135 public int countNumbersWithUniqueDigits (int n ) {
218- for (var e : dp) {
219- Arrays . fill(e, - 1 );
220- }
221- return dfs(n, 0 , true );
136+ f = new Integer [n][1 << 10 ];
137+ return dfs(n - 1 , 0 , true );
222138 }
223139
224- private int dfs (int pos , int mask , boolean lead ) {
225- if (pos <= 0 ) {
140+ private int dfs (int i , int mask , boolean lead ) {
141+ if (i < 0 ) {
226142 return 1 ;
227143 }
228- if (! lead && dp[pos ][mask] != - 1 ) {
229- return dp[pos ][mask];
144+ if (! lead && f[i ][mask] != null ) {
145+ return f[i ][mask];
230146 }
231147 int ans = 0 ;
232- for (int i = 0 ; i < 10 ; ++ i ) {
233- if ((( mask >> i) & 1 ) == 1 ) {
148+ for (int j = 0 ; j <= 9 ; ++ j ) {
149+ if ((mask >> j & 1 ) == 1 ) {
234150 continue ;
235151 }
236- if (i == 0 && lead ) {
237- ans += dfs(pos - 1 , mask, lead );
152+ if (lead && j == 0 ) {
153+ ans += dfs(i - 1 , mask, true );
238154 } else {
239- ans += dfs(pos - 1 , mask | ( 1 << i) , false );
155+ ans += dfs(i - 1 , mask | 1 << j , false );
240156 }
241157 }
242158 if (! lead) {
243- dp[pos ][mask] = ans;
159+ f[i ][mask] = ans;
244160 }
245161 return ans;
246162 }
@@ -252,33 +168,33 @@ class Solution {
252168``` cpp
253169class Solution {
254170public:
255- int dp[ 10] [ 1 << 11 ] ;
256-
257171 int countNumbersWithUniqueDigits(int n) {
258- memset(dp, -1, sizeof dp);
259- return dfs(n, 0, true);
260- }
261-
262- int dfs (int pos, int mask, bool lead) {
263- if (pos <= 0) {
264- return 1;
265- }
266- if (!lead && dp[ pos] [ mask ] != -1) {
267- return dp[ pos] [ mask ] ;
268- }
269- int ans = 0;
270- for (int i = 0; i < 10; ++i) {
271- if ((mask >> i) & 1) continue;
272- if (i == 0 && lead) {
273- ans += dfs(pos - 1, mask, lead);
274- } else {
275- ans += dfs(pos - 1, mask | 1 << i, false);
172+ int f[ n + 1] [ 1 << 10 ] ;
173+ memset(f, -1, sizeof(f));
174+ auto dfs = [ &] (auto&& dfs, int i, int mask, bool lead) -> int {
175+ if (i < 0) {
176+ return 1;
276177 }
277- }
278- if (!lead) {
279- dp[ pos] [ mask ] = ans;
280- }
281- return ans;
178+ if (!lead && f[ i] [ mask ] != -1) {
179+ return f[ i] [ mask ] ;
180+ }
181+ int ans = 0;
182+ for (int j = 0; j <= 9; ++j) {
183+ if (mask >> j & 1) {
184+ continue;
185+ }
186+ if (lead && j == 0) {
187+ ans += dfs(dfs, i - 1, mask, true);
188+ } else {
189+ ans += dfs(dfs, i - 1, mask | 1 << i, false);
190+ }
191+ }
192+ if (!lead) {
193+ f[ i] [ mask ] = ans;
194+ }
195+ return ans;
196+ };
197+ return dfs(dfs, n - 1, 0, true);
282198 }
283199};
284200```
@@ -287,39 +203,69 @@ public:
287203
288204```go
289205func countNumbersWithUniqueDigits(n int) int {
290- dp := make([][]int, 10)
291- for i := range dp {
292- dp[i] = make([]int, 1<<11)
293- for j := range dp[i] {
294- dp[i][j] = -1
206+ f := make([][1 << 10]int, n)
207+ for i := range f {
208+ for j := range f[i] {
209+ f[i][j] = -1
295210 }
296211 }
297- var dfs func(int, int, bool) int
298- dfs = func(pos , mask int, lead bool) int {
299- if pos <= 0 {
212+ var dfs func(i, mask int, lead bool) int
213+ dfs = func(i , mask int, lead bool) int {
214+ if i < 0 {
300215 return 1
301216 }
302- if !lead && dp[pos ][mask] != -1 {
303- return dp[pos ][mask]
217+ if !lead && f[i ][mask] != -1 {
218+ return f[i ][mask]
304219 }
305220 ans := 0
306- for i := 0; i < 10; i ++ {
307- if (( mask >> i) & 1) == 1 {
221+ for j := 0; j < 10; j ++ {
222+ if mask>>j&1 == 1 {
308223 continue
309224 }
310- if i == 0 && lead {
311- ans += dfs(pos -1, mask, lead )
225+ if lead && j == 0 {
226+ ans += dfs(i -1, mask, true )
312227 } else {
313- ans += dfs(pos -1, mask|1<<i , false)
228+ ans += dfs(i -1, mask|1<<j , false)
314229 }
315230 }
316231 if !lead {
317- dp[pos ][mask] = ans
232+ f[i ][mask] = ans
318233 }
319234 return ans
320235 }
236+ return dfs(n-1, 0, true)
237+ }
238+ ```
239+
240+ #### TypeScript
321241
322- return dfs(n, 0, true)
242+ ``` ts
243+ function countNumbersWithUniqueDigits(n : number ): number {
244+ const f: number [][] = Array .from ({ length: n }, () => Array (1 << 10 ).fill (- 1 ));
245+ const dfs = (i : number , mask : number , lead : boolean ): number => {
246+ if (i < 0 ) {
247+ return 1 ;
248+ }
249+ if (! lead && f [i ][mask ] !== - 1 ) {
250+ return f [i ][mask ];
251+ }
252+ let ans = 0 ;
253+ for (let j = 0 ; j < 10 ; ++ j ) {
254+ if ((mask >> j ) & 1 ) {
255+ continue ;
256+ }
257+ if (lead && j === 0 ) {
258+ ans += dfs (i - 1 , mask , true );
259+ } else {
260+ ans += dfs (i - 1 , mask | (1 << j ), false );
261+ }
262+ }
263+ if (! lead ) {
264+ f [i ][mask ] = ans ;
265+ }
266+ return ans ;
267+ };
268+ return dfs (n - 1 , 0 , true );
323269}
324270```
325271
0 commit comments