Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1b756af

Browse files
feat: add solutions to lc problem: No.0233 (doocs#3539)
No.0233.Number of Digit One
1 parent c238c6b commit 1b756af

File tree

8 files changed

+398
-294
lines changed

8 files changed

+398
-294
lines changed

‎solution/0200-0299/0233.Number of Digit One/README.md‎

Lines changed: 127 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,22 @@ $$
6666

6767
基本步骤如下:
6868

69-
1. 将数字 $n$ 转为 int 数组 $a,ドル其中 $a[1]$ 为最低位,而 $a[len]$ 为最高位;
70-
1. 根据题目信息,设计函数 $dfs(),ドル对于本题,我们定义 $dfs(pos, cnt, limit),ドル答案为 $dfs(len, 0, true)$。
69+
我们首先将数字 $n$ 转化为字符串 $s$。然后我们设计一个函数 $\textit{dfs}(i, \textit{cnt}, \textit{limit}),ドル其中:
7170

72-
其中:
71+
- 数字 $i$ 表示当前搜索到的位置,我们从高位开始搜索,即 $i = 0$ 表示最高位。
72+
- 数字 $\textit{cnt}$ 表示当前数字中 1ドル$ 出现的次数。
73+
- 布尔值 $\textit{limit}$ 表示当前是否受到上界的限制。
7374

74-
- `pos` 表示数字的位数,从末位或者第一位开始,一般根据题目的数字构造性质来选择顺序。对于本题,我们选择从高位开始,因此,`pos` 的初始值为 `len`;
75-
- `cnt` 表示当前数字中包含的 1ドル$ 的个数。
76-
- `limit` 表示可填的数字的限制,如果无限制,那么可以选择 $[0,1,..9],ドル否则,只能选择 $[0,..a[pos]]$。如果 `limit``true` 且已经取到了能取到的最大值,那么下一个 `limit` 同样为 `true`;如果 `limit``true` 但是还没有取到最大值,或者 `limit``false`,那么下一个 `limit``false`
75+
函数的执行过程如下:
7776

78-
关于函数的实现细节,可以参考下面的代码。
77+
如果 $i$ 超过了数字 $n$ 的长度,说明搜索结束,直接返回 $cnt$。如果 $\textit{limit}$ 为真,那么 $up$ 为当前数字的第 $i$ 位,否则 $up = 9$。接下来,我们遍历 $j$ 从 0ドル$ 到 $up,ドル对于每一个 $j$:
7978

80-
时间复杂度 $O(\log n)$。
79+
- 如果 $j$ 等于 1ドル,ドル我们将 $cnt$ 加一。
80+
- 递归调用 $\textit{dfs}(i + 1, \textit{cnt}, \textit{limit} \land j = up)$。
81+
82+
答案为 $\textit{dfs}(0, 0, \text{True})$。
83+
84+
时间复杂度 $O(m^2 \times D),ドル空间复杂度 $O(m^2)$。其中 $m$ 为数字 $n$ 的长度,而 $D = 10$。
8185

8286
相似题目:
8387

@@ -96,57 +100,48 @@ $$
96100
class Solution:
97101
def countDigitOne(self, n: int) -> int:
98102
@cache
99-
def dfs(pos, cnt, limit):
100-
if pos <=0:
103+
def dfs(i: int, cnt: int, limit: bool) -> int:
104+
if i >=len(s):
101105
return cnt
102-
up = a[pos] if limit else 9
106+
up = int(s[i]) if limit else 9
103107
ans = 0
104-
for i in range(up + 1):
105-
ans += dfs(pos - 1, cnt + (i == 1), limit and i == up)
108+
for j in range(up + 1):
109+
ans += dfs(i + 1, cnt + (j == 1), limit and j == up)
106110
return ans
107111

108-
a = [0] * 12
109-
l = 1
110-
while n:
111-
a[l] = n % 10
112-
n //= 10
113-
l += 1
114-
return dfs(l, 0, True)
112+
s = str(n)
113+
return dfs(0, 0, True)
115114
```
116115

117116
#### Java
118117

119118
```java
120119
class Solution {
121-
private int[] a = new int[12];
122-
private int[][] dp = new int[12][12];
120+
private int m;
121+
private char[] s;
122+
private Integer[][] f;
123123

124124
public int countDigitOne(int n) {
125-
int len = 0;
126-
while (n > 0) {
127-
a[++len] = n % 10;
128-
n /= 10;
129-
}
130-
for (var e : dp) {
131-
Arrays.fill(e, -1);
132-
}
133-
return dfs(len, 0, true);
125+
s = String.valueOf(n).toCharArray();
126+
m = s.length;
127+
f = new Integer[m][m];
128+
return dfs(0, 0, true);
134129
}
135130

136-
private int dfs(int pos, int cnt, boolean limit) {
137-
if (pos <=0) {
131+
private int dfs(int i, int cnt, boolean limit) {
132+
if (i >= m) {
138133
return cnt;
139134
}
140-
if (!limit && dp[pos][cnt] != -1) {
141-
return dp[pos][cnt];
135+
if (!limit && f[i][cnt] != null) {
136+
return f[i][cnt];
142137
}
143-
int up = limit ? a[pos] : 9;
138+
int up = limit ? s[i] -'0' : 9;
144139
int ans = 0;
145-
for (int i = 0; i <= up; ++i) {
146-
ans += dfs(pos - 1, cnt + (i == 1 ? 1 : 0), limit && i == up);
140+
for (int j = 0; j <= up; ++j) {
141+
ans += dfs(i + 1, cnt + (j == 1 ? 1 : 0), limit && j == up);
147142
}
148143
if (!limit) {
149-
dp[pos][cnt] = ans;
144+
f[i][cnt] = ans;
150145
}
151146
return ans;
152147
}
@@ -158,35 +153,29 @@ class Solution {
158153
```cpp
159154
class Solution {
160155
public:
161-
int a[12];
162-
int dp[12][12];
163-
164156
int countDigitOne(int n) {
165-
int len = 0;
166-
while (n) {
167-
a[++len] = n % 10;
168-
n /= 10;
169-
}
170-
memset(dp, -1, sizeof dp);
171-
return dfs(len, 0, true);
172-
}
173-
174-
int dfs(int pos, int cnt, bool limit) {
175-
if (pos <= 0) {
176-
return cnt;
177-
}
178-
if (!limit && dp[pos][cnt] != -1) {
179-
return dp[pos][cnt];
180-
}
181-
int ans = 0;
182-
int up = limit ? a[pos] : 9;
183-
for (int i = 0; i <= up; ++i) {
184-
ans += dfs(pos - 1, cnt + (i == 1), limit && i == up);
185-
}
186-
if (!limit) {
187-
dp[pos][cnt] = ans;
188-
}
189-
return ans;
157+
string s = to_string(n);
158+
int m = s.size();
159+
int f[m][m];
160+
memset(f, -1, sizeof(f));
161+
auto dfs = [&](auto&& dfs, int i, int cnt, bool limit) -> int {
162+
if (i >= m) {
163+
return cnt;
164+
}
165+
if (!limit && f[i][cnt] != -1) {
166+
return f[i][cnt];
167+
}
168+
int up = limit ? s[i] - '0' : 9;
169+
int ans = 0;
170+
for (int j = 0; j <= up; ++j) {
171+
ans += dfs(dfs, i + 1, cnt + (j == 1), limit && j == up);
172+
}
173+
if (!limit) {
174+
f[i][cnt] = ans;
175+
}
176+
return ans;
177+
};
178+
return dfs(dfs, 0, 0, true);
190179
}
191180
};
192181
```
@@ -195,67 +184,103 @@ public:
195184
196185
```go
197186
func countDigitOne(n int) int {
198-
a := make([]int, 12)
199-
dp := make([][]int, 12)
200-
for i := range dp {
201-
dp[i] = make([]int, 12)
202-
for j := range dp[i] {
203-
dp[i][j] = -1
187+
s := strconv.Itoa(n)
188+
m := len(s)
189+
f := make([][]int, m)
190+
for i := range f {
191+
f[i] = make([]int, m)
192+
for j := range f[i] {
193+
f[i][j] = -1
204194
}
205195
}
206-
l := 0
207-
for n > 0 {
208-
l++
209-
a[l] = n % 10
210-
n /= 10
211-
}
212-
var dfs func(int, int, bool) int
213-
dfs = func(pos, cnt int, limit bool) int {
214-
if pos <= 0 {
196+
var dfs func(i, cnt int, limit bool) int
197+
dfs = func(i, cnt int, limit bool) int {
198+
if i >= m {
215199
return cnt
216200
}
217-
if !limit && dp[pos][cnt] != -1 {
218-
return dp[pos][cnt]
201+
if !limit && f[i][cnt] != -1 {
202+
return f[i][cnt]
219203
}
220204
up := 9
221205
if limit {
222-
up = a[pos]
206+
up = int(s[i] - '0')
223207
}
224208
ans := 0
225-
for i := 0; i <= up; i++ {
226-
t := cnt
227-
if i == 1 {
228-
t++
209+
for j := 0; j <= up; j++ {
210+
t := 0
211+
if j == 1 {
212+
t = 1
229213
}
230-
ans += dfs(pos-1, t, limit && i == up)
214+
ans += dfs(i+1, cnt+t, limit && j == up)
231215
}
232216
if !limit {
233-
dp[pos][cnt] = ans
217+
f[i][cnt] = ans
234218
}
235219
return ans
236220
}
237-
return dfs(l, 0, true)
221+
return dfs(0, 0, true)
222+
}
223+
```
224+
225+
#### TypeScript
226+
227+
```ts
228+
function countDigitOne(n: number): number {
229+
const s = n.toString();
230+
const m = s.length;
231+
const f: number[][] = Array.from({ length: m }, () => Array(m).fill(-1));
232+
const dfs = (i: number, cnt: number, limit: boolean): number => {
233+
if (i >= m) {
234+
return cnt;
235+
}
236+
if (!limit && f[i][cnt] !== -1) {
237+
return f[i][cnt];
238+
}
239+
const up = limit ? +s[i] : 9;
240+
let ans = 0;
241+
for (let j = 0; j <= up; ++j) {
242+
ans += dfs(i + 1, cnt + (j === 1 ? 1 : 0), limit && j === up);
243+
}
244+
if (!limit) {
245+
f[i][cnt] = ans;
246+
}
247+
return ans;
248+
};
249+
return dfs(0, 0, true);
238250
}
239251
```
240252

241253
#### C#
242254

243255
```cs
244256
public class Solution {
257+
private int m;
258+
private char[] s;
259+
private int?[,] f;
260+
245261
public int CountDigitOne(int n) {
246-
if (n <= 0) return 0;
247-
if (n < 10) return 1;
248-
return CountDigitOne(n / 10 - 1) * 10 + n / 10 + CountDigitOneOfN(n / 10) * (n % 10 + 1) + (n % 10 >= 1 ? 1 : 0);
262+
s = n.ToString().ToCharArray();
263+
m = s.Length;
264+
f = new int?[m, m];
265+
return Dfs(0, 0, true);
249266
}
250267

251-
private int CountDigitOneOfN(int n) {
252-
var count = 0;
253-
while (n > 0)
254-
{
255-
if (n % 10 == 1) ++count;
256-
n /= 10;
268+
private int Dfs(int i, int cnt, bool limit) {
269+
if (i >= m) {
270+
return cnt;
257271
}
258-
return count;
272+
if (!limit && f[i, cnt] != null) {
273+
return f[i, cnt].Value;
274+
}
275+
int up = limit ? s[i] - '0' : 9;
276+
int ans = 0;
277+
for (int j = 0; j <= up; ++j) {
278+
ans += Dfs(i + 1, cnt + (j == 1 ? 1 : 0), limit && j == up);
279+
}
280+
if (!limit) {
281+
f[i, cnt] = ans;
282+
}
283+
return ans;
259284
}
260285
}
261286
```

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /