Skip to content

Commit da3ed3d

Browse files
authored
feat: add solutions to lc problem: No.0788 (#3543)
No.0788.Rotated Digits
1 parent d28b39b commit da3ed3d

File tree

9 files changed

+475
-351
lines changed

9 files changed

+475
-351
lines changed

solution/0700-0799/0788.Rotated Digits/README.md

Lines changed: 149 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ tags:
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>
@@ -56,9 +56,9 @@ tags:
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
126126
class Solution {
127127
public:
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 -->
@@ -204,18 +227,17 @@ $$
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

@@ -234,65 +256,53 @@ $$
234256
class 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
261278
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;
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
305315
class Solution {
306316
public:
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
348351
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}
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

Comments
 (0)