29
29
30
30
<pre ><strong >输入:</strong > 10
31
31
<strong >输出:</strong > 4
32
- <strong >解释:</strong >
32
+ <strong >解释:</strong >
33
33
在[1, 10]中有四个好数: 2, 5, 6, 9。
34
34
注意 1 和 10 不是好数, 因为他们在旋转之后不变。
35
35
</pre >
56
56
57
57
我们先用一个长度为 $10$ 的数组 $d$ 记录每个有效数字对应的旋转数字,在这道题中,有效数字有 $[ 0, 1, 8, 2, 5, 6, 9] $,分别对应旋转数字 $[ 0, 1, 8, 5, 2, 9, 6] $。如果不是有效数字,我们将对应的旋转数字设为 $-1$。
58
58
59
- 然后遍历数字 $x$ 的每一位数字 $v$,如果 $v$ 不是有效数字,说明 $x$ 不是好数,直接返回 ` false ` 。否则,我们将数字 $v$ 对应的旋转数字 $d[ v] $ 加入到 $y$ 中。最后,判断 $x$ 和 $y$ 是否相等,若不相等,则说明 $x$ 是好数,返回 ` true ` 。
59
+ 然后遍历数字 $x$ 的每一位数字 $v$,如果 $v$ 不是有效数字,说明 $x$ 不是好数,直接返回 $\textit{ false}$ 。否则,我们将数字 $v$ 对应的旋转数字 $d[ v] $ 加入到 $y$ 中。最后,判断 $x$ 和 $y$ 是否相等,若不相等,则说明 $x$ 是好数,返回 $\textit{ true}$ 。
60
60
61
- 时间复杂度 $O(n\times \log n)$。
61
+ 时间复杂度 $O(n \times \log n)$,其中 $n$ 为题目给定的数字。空间复杂度 $O(1 )$。
62
62
63
63
相似题目:
64
64
@@ -125,30 +125,28 @@ class Solution {
125
125
``` cpp
126
126
class Solution {
127
127
public:
128
- const vector<int > d = {0, 1, 5, -1, -1, 2, 9, -1, 8, 6};
129
-
130
128
int rotatedDigits(int n) {
129
+ int d[ 10] = {0, 1, 5, -1, -1, 2, 9, -1, 8, 6};
130
+ auto check = [ &] (int x) -> bool {
131
+ int y = 0, t = x;
132
+ int k = 1;
133
+ while (t) {
134
+ int v = t % 10;
135
+ if (d[ v] == -1) {
136
+ return false;
137
+ }
138
+ y = d[ v] * k + y;
139
+ k * = 10;
140
+ t /= 10;
141
+ }
142
+ return x != y;
143
+ };
131
144
int ans = 0;
132
145
for (int i = 1; i <= n; ++i) {
133
146
ans += check(i);
134
147
}
135
148
return ans;
136
149
}
137
-
138
- bool check (int x) {
139
- int y = 0, t = x;
140
- int k = 1;
141
- while (t) {
142
- int v = t % 10;
143
- if (d[ v] == -1) {
144
- return false;
145
- }
146
- y = d[ v] * k + y;
147
- k * = 10;
148
- t /= 10;
149
- }
150
- return x != y;
151
- }
152
150
};
153
151
```
154
152
@@ -180,6 +178,31 @@ func rotatedDigits(n int) int {
180
178
}
181
179
```
182
180
181
+ #### TypeScript
182
+
183
+ ``` ts
184
+ function rotatedDigits(n : number ): number {
185
+ const d: number [] = [0 , 1 , 5 , - 1 , - 1 , 2 , 9 , - 1 , 8 , 6 ];
186
+ const check = (x : number ): boolean => {
187
+ let y = 0 ;
188
+ let t = x ;
189
+ let k = 1 ;
190
+
191
+ while (t > 0 ) {
192
+ const v = t % 10 ;
193
+ if (d [v ] === - 1 ) {
194
+ return false ;
195
+ }
196
+ y = d [v ] * k + y ;
197
+ k *= 10 ;
198
+ t = Math .floor (t / 10 );
199
+ }
200
+ return x !== y ;
201
+ };
202
+ return Array .from ({ length: n }, (_ , i ) => i + 1 ).filter (check ).length ;
203
+ }
204
+ ```
205
+
183
206
<!-- tabs: end -->
184
207
185
208
<!-- solution: end -->
204
227
205
228
基本步骤如下:
206
229
207
- 1 . 将数字 $n$ 转为 int 数组 $a$,其中 $a[ 1] $ 为最低位,而 $a[ len] $ 为最高位;
208
- 1 . 根据题目信息,设计函数 $dfs()$,对于本题,我们定义 $dfs(pos, ok, limit)$,答案为 $dfs(len, 0, true)$。
230
+ 我们将数字 $n$ 转为字符串 $s$。然后定义函数 $\textit{dfs}(i, \textit{ok}, \textit{limit})$,其中 $i$ 表示数字的位数,数字 $\textit{ok}$ 表示当前数字是否满足题目要求,布尔值 $\textit{limit}$ 表示可填的数字的限制。
209
231
210
- 其中 :
232
+ 函数的执行逻辑如下 :
211
233
212
- - ` pos ` 表示数字的位数,从末位或者第一位开始,一般根据题目的数字构造性质来选择顺序。对于本题,我们选择从高位开始,因此,` pos ` 的初始值为 ` len ` ;
213
- - ` ok ` 表示当前数字是否满足题目要求(对于本题,如果数字出现 $[ 2, 5, 6, 9] $ 则满足)
214
- - ` limit ` 表示可填的数字的限制,如果无限制,那么可以选择 $[ 0,1,..9] $,否则,只能选择 $[ 0,..a[ pos]] $。如果 ` limit ` 为 ` true ` 且已经取到了能取到的最大值,那么下一个 ` limit ` 同样为 ` true ` ;如果 ` limit ` 为 ` true ` 但是还没有取到最大值,或者 ` limit ` 为 ` false ` ,那么下一个 ` limit ` 为 ` false ` 。
234
+ 如果 $i$ 大于等于字符串 $s$ 的长度,返回 $\textit{ok}$;
215
235
216
- 关于函数的实现细节,可以参考下面的代码。
236
+ 否则,我们获取当前位的数字 $up$,如果 $\textit{limit}$ 为 $\textit{true}$,则 $up$ 为当前位的数字,否则 $up$ 为 $9$;
217
237
218
- 时间复杂度 $O(\log n)$。
238
+ 接下来,我们遍历 $[ 0,..up] $,如果 $j$ 是有效数字 $[ 0, 1, 8] $,则递归调用 $\textit{dfs}(i + 1, \textit{ok}, \textit{limit} \land j = \textit{up})$;如果 $j$ 是有效数字 $[ 2, 5, 6, 9] $,则递归调用 $\textit{dfs}(i + 1, 1, \textit{limit} \land j = \textit{up})$;将所有递归调用的结果累加并返回。
239
+
240
+ 时间复杂度 $O(\log n \times D)$,空间复杂度 $O(\log n)$。其中 $D = 10$。
219
241
220
242
相似题目:
221
243
234
256
class Solution :
235
257
def rotatedDigits (self , n : int ) -> int :
236
258
@cache
237
- def dfs (pos , ok , limit ) :
238
- if pos <= 0 :
259
+ def dfs (i : int , ok : int , limit : bool ) -> int :
260
+ if i >= len (s) :
239
261
return ok
240
- up = a[pos] if limit else 9
262
+ up = int (s[i]) if limit else 9
241
263
ans = 0
242
- for i in range (up + 1 ):
243
- if i in (0 , 1 , 8 ):
244
- ans += dfs(pos - 1 , ok, limit and i == up)
245
- if i in (2 , 5 , 6 , 9 ):
246
- ans += dfs(pos - 1 , 1 , limit and i == up)
264
+ for j in range (up + 1 ):
265
+ if j in (0 , 1 , 8 ):
266
+ ans += dfs(i + 1 , ok, limit and j == up)
267
+ elif j in (2 , 5 , 6 , 9 ):
268
+ ans += dfs(i + 1 , 1 , limit and j == up)
247
269
return ans
248
270
249
- a = [0 ] * 6
250
- l = 1
251
- while n:
252
- a[l] = n % 10
253
- n //= 10
254
- l += 1
255
- return dfs(l, 0 , True )
271
+ s = str (n)
272
+ return dfs(0 , 0 , True )
256
273
```
257
274
258
275
#### Java
259
276
260
277
``` java
261
278
class Solution {
262
- private int [] a = new int [ 6 ] ;
263
- private int [][] dp = new int [ 6 ][ 2 ] ;
279
+ private char [] s ;
280
+ private Integer [][] f ;
264
281
265
282
public int rotatedDigits (int n ) {
266
- int len = 0 ;
267
- for (var e : dp) {
268
- Arrays . fill(e, - 1 );
269
- }
270
- while (n > 0 ) {
271
- a[++ len] = n % 10 ;
272
- n /= 10 ;
273
- }
274
- return dfs(len, 0 , true );
283
+ s = String . valueOf(n). toCharArray();
284
+ f = new Integer [s. length][2 ];
285
+ return dfs(0 , 0 , true );
275
286
}
276
287
277
- private int dfs (int pos , int ok , boolean limit ) {
278
- if (pos <= 0 ) {
288
+ private int dfs (int i , int ok , boolean limit ) {
289
+ if (i >= s . length ) {
279
290
return ok;
280
291
}
281
- if (! limit && dp[pos ][ok] != - 1 ) {
282
- return dp[pos ][ok];
292
+ if (! limit && f[i ][ok] != null ) {
293
+ return f[i ][ok];
283
294
}
284
- int up = limit ? a[pos] : 9 ;
295
+ int up = limit ? s[i] - ' 0 ' : 9 ;
285
296
int ans = 0 ;
286
- for (int i = 0 ; i <= up; ++ i) {
287
- if (i == 0 || i == 1 || i == 8 ) {
288
- ans += dfs(pos - 1 , ok, limit && i == up);
289
- }
290
- if (i == 2 || i == 5 || i == 6 || i == 9 ) {
291
- ans += dfs(pos - 1 , 1 , limit && i == up);
297
+ for (int j = 0 ; j <= up; ++ j) {
298
+ if (j == 0 || j == 1 || j == 8 ) {
299
+ ans += dfs(i + 1 , ok, limit && j == up);
300
+ } else if (j == 2 || j == 5 || j == 6 || j == 9 ) {
301
+ ans += dfs(i + 1 , 1 , limit && j == up);
292
302
}
293
303
}
294
304
if (! limit) {
295
- dp[pos ][ok] = ans;
305
+ f[i ][ok] = ans;
296
306
}
297
307
return ans;
298
308
}
@@ -304,40 +314,33 @@ class Solution {
304
314
``` cpp
305
315
class Solution {
306
316
public:
307
- int a[ 6] ;
308
- int dp[ 6] [ 2 ] ;
309
-
310
317
int rotatedDigits(int n) {
311
- memset(dp, -1, sizeof dp);
312
- int len = 0;
313
- while (n) {
314
- a[++len] = n % 10;
315
- n /= 10;
316
- }
317
- return dfs(len, 0 , true );
318
- }
319
-
320
- int dfs (int pos, int ok, bool limit) {
321
- if (pos <= 0) {
322
- return ok;
323
- }
324
- if (!limit && dp[ pos] [ ok ] != -1) {
325
- return dp[ pos] [ ok ] ;
326
- }
327
- int up = limit ? a[ pos] : 9;
328
- int ans = 0;
329
- for (int i = 0; i <= up; ++i) {
330
- if (i == 0 || i == 1 || i == 8) {
331
- ans += dfs(pos - 1, ok, limit && i == up);
318
+ string s = to_string(n);
319
+ int m = s.size();
320
+ int f[ m] [ 2 ] ;
321
+ memset(f, -1, sizeof(f));
322
+ auto dfs = [ &] (auto&& dfs, int i, int ok, bool limit) -> int {
323
+ if (i >= m) {
324
+ return ok;
332
325
}
333
- if (i == 2 || i == 5 || i == 6 || i == 9 ) {
334
- ans += dfs(pos - 1, 1, limit && i == up) ;
326
+ if (!limit && f [ i ] [ ok ] != -1 ) {
327
+ return f [ i ] [ ok ] ;
335
328
}
336
- }
337
- if (!limit) {
338
- dp[ pos] [ ok ] = ans;
339
- }
340
- return ans;
329
+ int up = limit ? s[ i] - '0' : 9;
330
+ int ans = 0;
331
+ for (int j = 0; j <= up; ++j) {
332
+ if (j == 0 || j == 1 || j == 8) {
333
+ ans += dfs(dfs, i + 1, ok, limit && j == up);
334
+ } else if (j == 2 || j == 5 || j == 6 || j == 9) {
335
+ ans += dfs(dfs, i + 1, 1, limit && j == up);
336
+ }
337
+ }
338
+ if (!limit) {
339
+ f[ i] [ ok ] = ans;
340
+ }
341
+ return ans;
342
+ };
343
+ return dfs(dfs, 0, 0, true);
341
344
}
342
345
};
343
346
```
@@ -346,46 +349,70 @@ public:
346
349
347
350
```go
348
351
func rotatedDigits(n int) int {
349
- a := make([]int, 6)
350
- dp := make([][2]int, 6)
351
- for i := range a {
352
- dp[i] = [2]int{-1, -1}
352
+ s := strconv.Itoa(n)
353
+ m := len(s)
354
+ f := make([][2]int, m)
355
+ for i := range f {
356
+ f[i] = [2]int{-1, -1}
353
357
}
354
- l := 0
355
- for n > 0 {
356
- l++
357
- a[l] = n % 10
358
- n /= 10
359
- }
360
-
361
- var dfs func(int, int, bool) int
362
- dfs = func(pos, ok int, limit bool) int {
363
- if pos <= 0 {
358
+ var dfs func(i, ok int, limit bool) int
359
+ dfs = func(i, ok int, limit bool) int {
360
+ if i >= m {
364
361
return ok
365
362
}
366
- if !limit && dp[pos ][ok] != -1 {
367
- return dp[pos ][ok]
363
+ if !limit && f[i ][ok] != -1 {
364
+ return f[i ][ok]
368
365
}
369
366
up := 9
370
367
if limit {
371
- up = a[pos]
368
+ up = int(s[i] - '0')
372
369
}
373
370
ans := 0
374
- for i := 0; i <= up; i++ {
375
- if i == 0 || i == 1 || i == 8 {
376
- ans += dfs(pos-1, ok, limit && i == up)
377
- }
378
- if i == 2 || i == 5 || i == 6 || i == 9 {
379
- ans += dfs(pos-1, 1, limit && i == up)
371
+ for j := 0; j <= up; j++ {
372
+ if j == 0 || j == 1 || j == 8 {
373
+ ans += dfs(i+1, ok, limit && j == up)
374
+ } else if j == 2 || j == 5 || j == 6 || j == 9 {
375
+ ans += dfs(i+1, 1, limit && j == up)
380
376
}
381
377
}
382
378
if !limit {
383
- dp[pos ][ok] = ans
379
+ f[i ][ok] = ans
384
380
}
385
381
return ans
386
382
}
383
+ return dfs(0, 0, true)
384
+ }
385
+ ```
386
+
387
+ #### TypeScript
387
388
388
- return dfs(l, 0, true)
389
+ ``` ts
390
+ function rotatedDigits(n : number ): number {
391
+ const s = n .toString ();
392
+ const m = s .length ;
393
+ const f: number [][] = Array .from ({ length: m }, () => Array (2 ).fill (- 1 ));
394
+ const dfs = (i : number , ok : number , limit : boolean ): number => {
395
+ if (i >= m ) {
396
+ return ok ;
397
+ }
398
+ if (! limit && f [i ][ok ] !== - 1 ) {
399
+ return f [i ][ok ];
400
+ }
401
+ const up = limit ? + s [i ] : 9 ;
402
+ let ans = 0 ;
403
+ for (let j = 0 ; j <= up ; ++ j ) {
404
+ if ([0 , 1 , 8 ].includes (j )) {
405
+ ans += dfs (i + 1 , ok , limit && j === up );
406
+ } else if ([2 , 5 , 6 , 9 ].includes (j )) {
407
+ ans += dfs (i + 1 , 1 , limit && j === up );
408
+ }
409
+ }
410
+ if (! limit ) {
411
+ f [i ][ok ] = ans ;
412
+ }
413
+ return ans ;
414
+ };
415
+ return dfs (0 , 0 , true );
389
416
}
390
417
```
391
418
0 commit comments