2929
3030<pre ><strong >输入:</strong > 10
3131<strong >输出:</strong > 4
32- <strong >解释:</strong >
32+ <strong >解释:</strong >
3333在[1, 10]中有四个好数: 2, 5, 6, 9。
3434注意 1 和 10 不是好数, 因为他们在旋转之后不变。
3535</pre >
5656
5757我们先用一个长度为 $10$ 的数组 $d$ 记录每个有效数字对应的旋转数字,在这道题中,有效数字有 $[ 0, 1, 8, 2, 5, 6, 9] $,分别对应旋转数字 $[ 0, 1, 8, 5, 2, 9, 6] $。如果不是有效数字,我们将对应的旋转数字设为 $-1$。
5858
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}$ 。
6060
61- 时间复杂度 $O(n\times \log n)$。
61+ 时间复杂度 $O(n \times \log n)$,其中 $n$ 为题目给定的数字。空间复杂度 $O(1 )$。
6262
6363相似题目:
6464
@@ -125,30 +125,28 @@ class Solution {
125125``` cpp
126126class Solution {
127127public:
128- const vector<int > d = {0, 1, 5, -1, -1, 2, 9, -1, 8, 6};
129-
130128 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+ };
131144 int ans = 0;
132145 for (int i = 1; i <= n; ++i) {
133146 ans += check(i);
134147 }
135148 return ans;
136149 }
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- }
152150};
153151```
154152
@@ -180,6 +178,31 @@ func rotatedDigits(n int) int {
180178}
181179```
182180
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+
183206<!-- tabs: end -->
184207
185208<!-- solution: end -->
204227
205228基本步骤如下:
206229
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}$ 表示可填的数字的限制。
209231
210- 其中 :
232+ 函数的执行逻辑如下 :
211233
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}$;
215235
216- 关于函数的实现细节,可以参考下面的代码。
236+ 否则,我们获取当前位的数字 $up$,如果 $\textit{limit}$ 为 $\textit{true}$,则 $up$ 为当前位的数字,否则 $up$ 为 $9$;
217237
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$。
219241
220242相似题目:
221243
234256class Solution :
235257 def rotatedDigits (self , n : int ) -> int :
236258 @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) :
239261 return ok
240- up = a[pos] if limit else 9
262+ up = int (s[i]) if limit else 9
241263 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)
247269 return ans
248270
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 )
256273```
257274
258275#### Java
259276
260277``` java
261278class Solution {
262- private int [] a = new int [ 6 ] ;
263- private int [][] dp = new int [ 6 ][ 2 ] ;
279+ private char [] s ;
280+ private Integer [][] f ;
264281
265282 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 );
275286 }
276287
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 ) {
279290 return ok;
280291 }
281- if (! limit && dp[pos ][ok] != - 1 ) {
282- return dp[pos ][ok];
292+ if (! limit && f[i ][ok] != null ) {
293+ return f[i ][ok];
283294 }
284- int up = limit ? a[pos] : 9 ;
295+ int up = limit ? s[i] - ' 0 ' : 9 ;
285296 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);
292302 }
293303 }
294304 if (! limit) {
295- dp[pos ][ok] = ans;
305+ f[i ][ok] = ans;
296306 }
297307 return ans;
298308 }
@@ -304,40 +314,33 @@ class Solution {
304314``` cpp
305315class Solution {
306316public:
307- int a[ 6] ;
308- int dp[ 6] [ 2 ] ;
309-
310317 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;
332325 }
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 ] ;
335328 }
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);
341344 }
342345};
343346```
@@ -346,46 +349,70 @@ public:
346349
347350```go
348351func 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}
353357 }
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 {
364361 return ok
365362 }
366- if !limit && dp[pos ][ok] != -1 {
367- return dp[pos ][ok]
363+ if !limit && f[i ][ok] != -1 {
364+ return f[i ][ok]
368365 }
369366 up := 9
370367 if limit {
371- up = a[pos]
368+ up = int(s[i] - '0')
372369 }
373370 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)
380376 }
381377 }
382378 if !limit {
383- dp[pos ][ok] = ans
379+ f[i ][ok] = ans
384380 }
385381 return ans
386382 }
383+ return dfs(0, 0, true)
384+ }
385+ ```
386+
387+ #### TypeScript
387388
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 );
389416}
390417```
391418
0 commit comments