Skip to content

Commit fffc636

Browse files
committed
feat: add solutions to lc problem: No.3747
1 parent 523bd6c commit fffc636

File tree

7 files changed

+552
-8
lines changed

7 files changed

+552
-8
lines changed

solution/3700-3799/3747.Count Distinct Integers After Removing Zeros/README.md

Lines changed: 189 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,32 +61,217 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3700-3799/3747.Co
6161

6262
<!-- solution:start -->
6363

64-
### 方法一
64+
### 方法一:数位 DP
65+
66+
题目实际上是要我们统计区间 $[1, n]$ 之间,数字中不含 0 的整数个数。我们可以使用数位 DP 来解决这个问题。
67+
68+
我们设计一个函数 $\text{dfs}(i, \text{zero}, \text{lead}, \text{limit})$,表示当前处理到数字的第 $i$ 位,用 $\text{zero}$ 表示当前数字中是否已经出现过非零数字,用 $\text{lead}$ 表示当前是否还在处理前导零,而 $\text{limit}$ 表示当前数字是否受上界限制的方案数。答案为 $\text{dfs}(0, 0, 1, 1)$。
69+
70+
函数 $\text{dfs}(i, \text{zero}, \text{lead}, \text{limit})$ 中,如果 $i$ 大于等于数字的长度,那么我们就可以判断 $\text{zero}$ 和 $\text{lead}$,如果 $\text{zero}$ 为假且 $\text{lead}$ 为假,说明当前数字中不含 0,我们就返回 $1$,否则返回 $0$。
71+
72+
对于 $\text{dfs}(i, \text{zero}, \text{lead}, \text{limit})$,我们可以枚举当前数位 $d$ 的值,然后递归计算 $\text{dfs}(i+1, \text{nxt\_zero}, \text{nxt\_lead}, \text{nxt\_limit})$,其中 $\text{nxt\_zero}$ 表示当前数字中是否已经出现过非零数字,$\text{nxt\_lead}$ 表示当前是否还在处理前导零,而 $\text{nxt\_limit}$ 表示当前数字是否受上界限制。如果 $\text{limit}$ 为真,那么 $up$ 就是当前数位的上界,否则 $up$ 为 $9$。
73+
74+
时间复杂度 $O(\log_{10} n \times D)$,空间复杂度 $O(\log_{10} n)$。其中 $D$ 表示数字 0 到 9 的个数。
6575

6676
<!-- tabs:start -->
6777

6878
#### Python3
6979

7080
```python
71-
81+
class Solution:
82+
def countDistinct(self, n: int) -> int:
83+
@cache
84+
def dfs(i: int, zero: bool, lead: bool, lim: bool) -> int:
85+
if i >= len(s):
86+
return 1 if (not zero and not lead) else 0
87+
up = int(s[i]) if lim else 9
88+
ans = 0
89+
for j in range(up + 1):
90+
nxt_zero = zero or (j == 0 and not lead)
91+
nxt_lead = lead and j == 0
92+
nxt_lim = lim and j == up
93+
ans += dfs(i + 1, nxt_zero, nxt_lead, nxt_lim)
94+
return ans
95+
96+
s = str(n)
97+
return dfs(0, False, True, True)
7298
```
7399

74100
#### Java
75101

76102
```java
77-
103+
class Solution {
104+
private char[] s;
105+
private Long[][][][] f;
106+
107+
public long countDistinct(long n) {
108+
s = String.valueOf(n).toCharArray();
109+
f = new Long[s.length][2][2][2];
110+
return dfs(0, 0, 1, 1);
111+
}
112+
113+
private long dfs(int i, int zero, int lead, int limit) {
114+
if (i == s.length) {
115+
return (zero == 0 && lead == 0) ? 1 : 0;
116+
}
117+
118+
if (limit == 0 && f[i][zero][lead][limit] != null) {
119+
return f[i][zero][lead][limit];
120+
}
121+
122+
int up = limit == 1 ? s[i] - '0' : 9;
123+
long ans = 0;
124+
for (int d = 0; d <= up; d++) {
125+
int nxtZero = zero == 1 || (d == 0 && lead == 0) ? 1 : 0;
126+
int nxtLead = (lead == 1 && d == 0) ? 1 : 0;
127+
int nxtLimit = (limit == 1 && d == up) ? 1 : 0;
128+
ans += dfs(i + 1, nxtZero, nxtLead, nxtLimit);
129+
}
130+
131+
if (limit == 0) {
132+
f[i][zero][lead][limit] = ans;
133+
}
134+
return ans;
135+
}
136+
}
78137
```
79138

80139
#### C++
81140

82141
```cpp
83-
142+
class Solution {
143+
public:
144+
long long countDistinct(long long n) {
145+
string s = to_string(n);
146+
int m = s.size();
147+
static long long f[20][2][2][2];
148+
memset(f, -1, sizeof(f));
149+
150+
auto dfs = [&](this auto&& dfs, int i, int zero, int lead, int limit) -> long long {
151+
if (i == m) {
152+
return (zero == 0 && lead == 0) ? 1 : 0;
153+
}
154+
if (!limit && f[i][zero][lead][limit] != -1) {
155+
return f[i][zero][lead][limit];
156+
}
157+
158+
int up = limit ? (s[i] - '0') : 9;
159+
long long ans = 0;
160+
for (int d = 0; d <= up; d++) {
161+
int nxtZero = zero || (d == 0 && !lead);
162+
int nxtLead = lead && d == 0;
163+
int nxtLimit = limit && d == up;
164+
ans += dfs(i + 1, nxtZero, nxtLead, nxtLimit);
165+
}
166+
167+
if (!limit) f[i][zero][lead][limit] = ans;
168+
return ans;
169+
};
170+
171+
return dfs(0, 0, 1, 1);
172+
}
173+
};
84174
```
85175

86176
#### Go
87177

88178
```go
179+
func countDistinct(n int64) int64 {
180+
s := []byte(fmt.Sprint(n))
181+
m := len(s)
182+
var f [20][2][2][2]int64
183+
for i := range f {
184+
for j := range f[i] {
185+
for k := range f[i][j] {
186+
for t := range f[i][j][k] {
187+
f[i][j][k][t] = -1
188+
}
189+
}
190+
}
191+
}
192+
193+
var dfs func(i, zero, lead, limit int) int64
194+
dfs = func(i, zero, lead, limit int) int64 {
195+
if i == m {
196+
if zero == 0 && lead == 0 {
197+
return 1
198+
}
199+
return 0
200+
}
201+
202+
if limit == 0 && f[i][zero][lead][limit] != -1 {
203+
return f[i][zero][lead][limit]
204+
}
205+
206+
up := 9
207+
if limit == 1 {
208+
up = int(s[i] - '0')
209+
}
210+
211+
var ans int64 = 0
212+
for d := 0; d <= up; d++ {
213+
nxtZero := zero
214+
if d == 0 && lead == 0 {
215+
nxtZero = 1
216+
}
217+
nxtLead := 0
218+
if lead == 1 && d == 0 {
219+
nxtLead = 1
220+
}
221+
nxtLimit := 0
222+
if limit == 1 && d == up {
223+
nxtLimit = 1
224+
}
225+
ans += dfs(i+1, nxtZero, nxtLead, nxtLimit)
226+
}
227+
228+
if limit == 0 {
229+
f[i][zero][lead][limit] = ans
230+
}
231+
return ans
232+
}
233+
234+
return dfs(0, 0, 1, 1)
235+
}
236+
```
89237

238+
#### TypeScript
239+
240+
```ts
241+
function countDistinct(n: number): number {
242+
const s = n.toString();
243+
const m = s.length;
244+
245+
const f: number[][][][] = Array.from({ length: m }, () =>
246+
Array.from({ length: 2 }, () => Array.from({ length: 2 }, () => Array(2).fill(-1))),
247+
);
248+
249+
const dfs = (i: number, zero: number, lead: number, limit: number): number => {
250+
if (i === m) {
251+
return zero === 0 && lead === 0 ? 1 : 0;
252+
}
253+
254+
if (limit === 0 && f[i][zero][lead][limit] !== -1) {
255+
return f[i][zero][lead][limit];
256+
}
257+
258+
const up = limit === 1 ? parseInt(s[i]) : 9;
259+
let ans = 0;
260+
for (let d = 0; d <= up; d++) {
261+
const nxtZero = zero === 1 || (d === 0 && lead === 0) ? 1 : 0;
262+
const nxtLead = lead === 1 && d === 0 ? 1 : 0;
263+
const nxtLimit = limit === 1 && d === up ? 1 : 0;
264+
ans += dfs(i + 1, nxtZero, nxtLead, nxtLimit);
265+
}
266+
267+
if (limit === 0) {
268+
f[i][zero][lead][limit] = ans;
269+
}
270+
return ans;
271+
};
272+
273+
return dfs(0, 0, 1, 1);
274+
}
90275
```
91276

92277
<!-- tabs:end -->

0 commit comments

Comments
 (0)