Skip to content

Commit 95ad570

Browse files
committed
feat: add solutions to lc problem: No.0788
No.0788.Rotated Digits
1 parent 589955a commit 95ad570

File tree

6 files changed

+484
-73
lines changed

6 files changed

+484
-73
lines changed

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

+196
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,37 @@
4747

4848
时间复杂度 $O(n\times \log n)$。
4949

50+
**方法二:数位 DP**
51+
52+
方法一的做法足以通过本题,但时间复杂度较高。如果题目的数据范围达到 $10^9$ 级别,则方法一的做法会超出时间限制。
53+
54+
这道题实际上是求在给定区间 $[l, r]$ 中,满足条件的数的个数。条件与数的大小无关,而只与数的组成有关,因此可以使用数位 DP 的思想求解。数位 DP 中,数的大小对复杂度的影响很小。
55+
56+
对于区间 $[l, r]$ 问题,我们一般会将其转化为 $[1, r]$ 问题,然后再减去 $[1, l - 1]$ 问题,即:
57+
58+
$$
59+
ans = \sum_{i=1}^{r} ans_i - \sum_{i=1}^{l-1} ans_i
60+
$$
61+
62+
不过对于本题而言,我们只需要求出区间 $[1, r]$ 的值即可。
63+
64+
这里我们用记忆化搜索来实现数位 DP。从起点向下搜索,到最底层得到方案数,一层层向上返回答案并累加,最后从搜索起点得到最终的答案。
65+
66+
基本步骤如下:
67+
68+
1. 将数字 $x$ 转为 int 数组 $a$,其中 $a[1]$ 为最低位,而 $a[len]$ 为最高位;
69+
1. 根据题目信息,设计函数 $dfs()$,对于本题,我们定义 $dfs(pos, ok, limit)$,答案为 $dfs(len, 0, true)$。
70+
71+
其中:
72+
73+
- `pos` 表示数字的位数,从末位或者第一位开始,一般根据题目的数字构造性质来选择顺序。对于本题,我们选择从高位开始,因此,`pos` 的初始值为 `len`
74+
- `ok` 表示当前数字是否满足题目要求(对于本题,如果数字出现 `2, 5, 6, 9` 则满足)
75+
- `limit` 表示可填的数字的限制,如果无限制,那么可以选择 $[0, 9]$,否则,只能选择 $[0, a[pos]]$。如果 `limit``true` 且已经取到了能取到的最大值,那么下一个 `limit` 同样为 `true`;如果 `limit``true` 但是还没有取到最大值,或者 `limit``false`,那么下一个 `limit``false`
76+
77+
关于函数的实现细节,可以参考下面的代码。
78+
79+
时间复杂度 $O(\log n)$。
80+
5081
<!-- tabs:start -->
5182

5283
### **Python3**
@@ -72,6 +103,31 @@ class Solution:
72103
return sum(check(i) for i in range(1, n + 1))
73104
```
74105

106+
```python
107+
class Solution:
108+
def rotatedDigits(self, n: int) -> int:
109+
@cache
110+
def dfs(pos, ok, limit):
111+
if pos <= 0:
112+
return ok
113+
up = a[pos] if limit else 9
114+
ans = 0
115+
for i in range(up + 1):
116+
if i in (0, 1, 8):
117+
ans += dfs(pos - 1, ok, limit and i == up)
118+
if i in (2, 5, 6, 9):
119+
ans += dfs(pos - 1, 1, limit and i == up)
120+
return ans
121+
122+
a = [0] * 6
123+
l = 1
124+
while n:
125+
a[l] = n % 10
126+
n //= 10
127+
l += 1
128+
return dfs(l, 0, True)
129+
```
130+
75131
### **Java**
76132

77133
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -116,6 +172,52 @@ class Solution {
116172
}
117173
```
118174

175+
```java
176+
class Solution {
177+
private int[] a = new int[6];
178+
private int[][] dp = new int[6][2];
179+
180+
public int rotatedDigits(int n) {
181+
return f(n);
182+
}
183+
184+
private int f(int x) {
185+
int len = 0;
186+
for (var e : dp) {
187+
Arrays.fill(e, -1);
188+
}
189+
while (x > 0) {
190+
a[++len] = x % 10;
191+
x /= 10;
192+
}
193+
return dfs(len, 0, true);
194+
}
195+
196+
private int dfs(int pos, int ok, boolean limit) {
197+
if (pos <= 0) {
198+
return ok;
199+
}
200+
if (!limit && dp[pos][ok] != -1) {
201+
return dp[pos][ok];
202+
}
203+
int up = limit ? a[pos] : 9;
204+
int ans = 0;
205+
for (int i = 0; i <= up; ++i) {
206+
if (i == 0 || i == 1 || i == 8) {
207+
ans += dfs(pos - 1, ok, limit && i == up);
208+
}
209+
if (i == 2 || i == 5 || i == 6 || i == 9) {
210+
ans += dfs(pos - 1, 1, limit && i == up);
211+
}
212+
}
213+
if (!limit) {
214+
dp[pos][ok] = ans;
215+
}
216+
return ans;
217+
}
218+
}
219+
```
220+
119221
### **C++**
120222

121223
```cpp
@@ -148,6 +250,52 @@ public:
148250
};
149251
```
150252
253+
```cpp
254+
class Solution {
255+
public:
256+
int a[6];
257+
int dp[6][2];
258+
259+
int rotatedDigits(int n) {
260+
return f(n);
261+
}
262+
263+
int f(int x) {
264+
memset(dp, -1, sizeof dp);
265+
int len = 0;
266+
while (x) {
267+
a[++len] = x % 10;
268+
x /= 10;
269+
}
270+
return dfs(len, 0, true);
271+
}
272+
273+
int dfs(int pos, int ok, bool limit) {
274+
if (pos <= 0) {
275+
return ok;
276+
}
277+
if (!limit && dp[pos][ok] != -1) {
278+
return dp[pos][ok];
279+
}
280+
int up = limit ? a[pos] : 9;
281+
int ans = 0;
282+
for (int i = 0; i <= up; ++i) {
283+
if (i == 0 || i == 1 || i == 8) {
284+
ans += dfs(pos - 1, ok, limit && i == up);
285+
}
286+
if (i == 2 || i == 5 || i == 6 || i == 9) {
287+
ans += dfs(pos - 1, 1, limit && i == up);
288+
}
289+
}
290+
if (!limit) {
291+
dp[pos][ok] = ans;
292+
}
293+
return ans;
294+
}
295+
296+
};
297+
```
298+
151299
### **Go**
152300

153301
```go
@@ -176,6 +324,54 @@ func rotatedDigits(n int) int {
176324
}
177325
```
178326

327+
```go
328+
func rotatedDigits(n int) int {
329+
a := make([]int, 6)
330+
dp := make([][]int, 6)
331+
for i := range a {
332+
dp[i] = make([]int, 2)
333+
for j := range dp[i] {
334+
dp[i][j] = -1
335+
}
336+
}
337+
l := 1
338+
for n > 0 {
339+
a[l] = n % 10
340+
n /= 10
341+
l++
342+
}
343+
344+
var dfs func(int, int, bool) int
345+
dfs = func(pos, ok int, limit bool) int {
346+
if pos <= 0 {
347+
return ok
348+
}
349+
if !limit && dp[pos][ok] != -1 {
350+
return dp[pos][ok]
351+
}
352+
up := 9
353+
if limit {
354+
up = a[pos]
355+
}
356+
ans := 0
357+
for i := 0; i <= up; i++ {
358+
if i == 0 || i == 1 || i == 8 {
359+
ans += dfs(pos-1, ok, limit && i == up)
360+
}
361+
if i == 2 || i == 5 || i == 6 || i == 9 {
362+
ans += dfs(pos-1, 1, limit && i == up)
363+
}
364+
}
365+
if !limit {
366+
dp[pos][ok] = ans
367+
}
368+
return ans
369+
}
370+
371+
return dfs(l, 0, true)
372+
}
373+
```
374+
179375
### **...**
180376

181377
```

0 commit comments

Comments
 (0)