Skip to content

Commit 17c3e8c

Browse files
committed
feat: update solutions to lc problems
* No.1012.Numbers With Repeated Digit * No.2373.Largest Local Values in a Matrix * No.2374.Node With Highest Edge Score * No.2375.Construct Smallest Number From DI String * No.2376.Count Special Integers
1 parent 63a2492 commit 17c3e8c

File tree

26 files changed

+553
-20
lines changed

26 files changed

+553
-20
lines changed

solution/0500-0599/0543.Diameter of Binary Tree/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232

3333
**方法一**:后序遍历求每个结点的深度,此过程中获取每个结点左右子树的最长伸展(深度),迭代获取最长路径。
3434

35-
类似题目[687. 最长同值路径](/solution/0600-0699/0687.Longest%20Univalue%20Path/README.md)
35+
相似题目[687. 最长同值路径](/solution/0600-0699/0687.Longest%20Univalue%20Path/README.md)
3636

3737
**方法二**:构建图,两次 DFS。
3838

39-
类似题目[1245. 树的直径](/solution/1200-1299/1245.Tree%20Diameter/README.md), [1522. N 叉树的直径](/solution/1500-1599/1522.Diameter%20of%20N-Ary%20Tree/README.md)
39+
相似题目[1245. 树的直径](/solution/1200-1299/1245.Tree%20Diameter/README.md), [1522. N 叉树的直径](/solution/1500-1599/1522.Diameter%20of%20N-Ary%20Tree/README.md)
4040

4141
<!-- tabs:start -->
4242

solution/0600-0699/0616.Add Bold Tag in String/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252

5353
**方法一:前缀树 + 区间合并**
5454

55-
类似题目[1065. 字符串的索引对](/solution/1000-1099/1065.Index%20Pairs%20of%20a%20String/README.md)[758. 字符串中的加粗单词](/solution/0700-0799/0758.Bold%20Words%20in%20String/README.md)
55+
相似题目[1065. 字符串的索引对](/solution/1000-1099/1065.Index%20Pairs%20of%20a%20String/README.md)[758. 字符串中的加粗单词](/solution/0700-0799/0758.Bold%20Words%20in%20String/README.md)
5656

5757
<!-- tabs:start -->
5858

solution/0600-0699/0687.Longest Univalue Path/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
<!-- 这里可写通用的实现逻辑 -->
4646

47-
类似题目[543. 二叉树的直径](/solution/0500-0599/0543.Diameter%20of%20Binary%20Tree/README.md)
47+
相似题目[543. 二叉树的直径](/solution/0500-0599/0543.Diameter%20of%20Binary%20Tree/README.md)
4848

4949
<!-- tabs:start -->
5050

solution/0700-0799/0758.Bold Words in String/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
**方法一:前缀树 + 区间合并**
5050

51-
类似题目[1065. 字符串的索引对](/solution/1000-1099/1065.Index%20Pairs%20of%20a%20String/README.md)[616. 给字符串添加加粗标签](/solution/0600-0699/0616.Add%20Bold%20Tag%20in%20String/README.md)
51+
相似题目[1065. 字符串的索引对](/solution/1000-1099/1065.Index%20Pairs%20of%20a%20String/README.md)[616. 给字符串添加加粗标签](/solution/0600-0699/0616.Add%20Bold%20Tag%20in%20String/README.md)
5252

5353
<!-- tabs:start -->
5454

solution/1000-1099/1012.Numbers With Repeated Digits/README.md

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,205 @@
4545

4646
<!-- 这里可写通用的实现逻辑 -->
4747

48+
**方法一:数位 DP**
49+
50+
题目求解 $[1,n]$ 范围内至少有 $1$ 位重复数字的正整数个数,我们可以转换为求解无重复数字的正整数个数 $cnt$,那么 $n-cnt$ 就是答案。
51+
52+
接下来我们就来求解 $[1,n]$ 范围内无重复数字的正整数个数。
53+
54+
定义 $m$ 表示数字 $n$ 的位数。我们可以将数字分成两类:(1) 数字位数小于 $m$;(2) 数字位数等于 $m$。
55+
56+
对于第一类,我们可以枚举数字的位数 $i$,其中 $i∈[1,m)$,第一位的数字不为 $0$,有 $[1,9]$ 可选,共 $9$ 种可能。剩余需要选择 $i-1$ 位数字,可选数字为 $[0,9]$ 的数字中除去第一位,共 $9$ 种可能。因此,第一类的数字共有:
57+
58+
$$
59+
\sum \limits_{i=1}^{m-1} 9\times A_{9}^{i-1}
60+
$$
61+
62+
对于第二类,数字的位数等于 $m$,我们从 $n$ 的高位(即 $i=m-1$)开始处理。不妨设 $n$ 当前位的数字为 $v$。
63+
64+
如果当前是 $n$ 的最高一位,那么数字不能为 $0$,可选数字为 $[1,v)$,否则可选数字为 $[0,v)$。若当前可选数字 $j$,那么剩余低位可选的数字总共有 $A_{10-(m-i)}^{i}$,累加到答案中。
65+
66+
以上我们算的是可选数字小于 $v$ 的情况,若等于 $v$,则需要继续外层循环,继续处理下一位。如果数字 $n$ 所有位均不重复,则 $n$ 本身也是一个特殊整数,需要累加到答案中。
67+
68+
时间复杂度 $O(m^2)$,其中 $m$ 是数字 $n$ 的位数,这里我们假定 $A_{m}^{n}$ 可以 $O(1)$ 时间算出。
69+
70+
相似题目:[2376.统计特殊整数](/solution/2300-2399/2376.Count%20Special%20Integers/README.md)
71+
4872
<!-- tabs:start -->
4973

5074
### **Python3**
5175

5276
<!-- 这里可写当前语言的特殊实现逻辑 -->
5377

5478
```python
55-
79+
class Solution:
80+
def numDupDigitsAtMostN(self, n: int) -> int:
81+
return n - self.f(n)
82+
83+
def f(self, n):
84+
def A(m, n):
85+
return 1 if n == 0 else A(m, n - 1) * (m - n + 1)
86+
87+
vis = [False] * 10
88+
ans = 0
89+
digits = [int(c) for c in str(n)[::-1]]
90+
m = len(digits)
91+
for i in range(1, m):
92+
ans += 9 * A(9, i - 1)
93+
for i in range(m - 1, -1, -1):
94+
v = digits[i]
95+
j = 1 if i == m - 1 else 0
96+
while j < v:
97+
if not vis[j]:
98+
ans += A(10 - (m - i), i)
99+
j += 1
100+
if vis[v]:
101+
break
102+
vis[v] = True
103+
if i == 0:
104+
ans += 1
105+
return ans
56106
```
57107

58108
### **Java**
59109

60110
<!-- 这里可写当前语言的特殊实现逻辑 -->
61111

62112
```java
113+
class Solution {
114+
public int numDupDigitsAtMostN(int n) {
115+
return n - f(n);
116+
}
117+
118+
public int f(int n) {
119+
List<Integer> digits = new ArrayList<>();
120+
while (n != 0) {
121+
digits.add(n % 10);
122+
n /= 10;
123+
}
124+
int m = digits.size();
125+
int ans = 0;
126+
for (int i = 1; i < m; ++i) {
127+
ans += 9 * A(9, i - 1);
128+
}
129+
boolean[] vis = new boolean[10];
130+
for (int i = m - 1; i >= 0; --i) {
131+
int v = digits.get(i);
132+
for (int j = i == m - 1 ? 1 : 0; j < v; ++j) {
133+
if (vis[j]) {
134+
continue;
135+
}
136+
ans += A(10 - (m - i), i);
137+
}
138+
if (vis[v]) {
139+
break;
140+
}
141+
vis[v] = true;
142+
if (i == 0) {
143+
++ans;
144+
}
145+
}
146+
return ans;
147+
}
148+
149+
private int A(int m, int n) {
150+
return n == 0 ? 1 : A(m, n - 1) * (m - n + 1);
151+
}
152+
}
153+
```
154+
155+
### **C++**
156+
157+
```cpp
158+
class Solution {
159+
public:
160+
int numDupDigitsAtMostN(int n) {
161+
return n - f(n);
162+
}
163+
164+
int f(int n) {
165+
int ans = 0;
166+
vector<int> digits;
167+
while (n) {
168+
digits.push_back(n % 10);
169+
n /= 10;
170+
}
171+
int m = digits.size();
172+
vector<bool> vis(10);
173+
for (int i = 1; i < m; ++i) {
174+
ans += 9 * A(9, i - 1);
175+
}
176+
for (int i = m - 1; ~i; --i) {
177+
int v = digits[i];
178+
for (int j = i == m - 1 ? 1 : 0; j < v; ++j) {
179+
if (!vis[j]) {
180+
ans += A(10 - (m - i), i);
181+
}
182+
}
183+
if (vis[v]) {
184+
break;
185+
}
186+
vis[v] = true;
187+
if (i == 0) {
188+
++ans;
189+
}
190+
}
191+
return ans;
192+
}
193+
194+
int A(int m, int n) {
195+
return n == 0 ? 1 : A(m, n - 1) * (m - n + 1);
196+
}
197+
};
198+
```
63199
200+
### **Go**
201+
202+
```go
203+
func numDupDigitsAtMostN(n int) int {
204+
return n - f(n)
205+
}
206+
207+
func f(n int) int {
208+
digits := []int{}
209+
for n != 0 {
210+
digits = append(digits, n%10)
211+
n /= 10
212+
}
213+
m := len(digits)
214+
vis := make([]bool, 10)
215+
ans := 0
216+
for i := 1; i < m; i++ {
217+
ans += 9 * A(9, i-1)
218+
}
219+
for i := m - 1; i >= 0; i-- {
220+
v := digits[i]
221+
j := 0
222+
if i == m-1 {
223+
j = 1
224+
}
225+
for ; j < v; j++ {
226+
if !vis[j] {
227+
ans += A(10-(m-i), i)
228+
}
229+
}
230+
if vis[v] {
231+
break
232+
}
233+
vis[v] = true
234+
if i == 0 {
235+
ans++
236+
}
237+
}
238+
return ans
239+
}
240+
241+
func A(m, n int) int {
242+
if n == 0 {
243+
return 1
244+
}
245+
return A(m, n-1) * (m - n + 1)
246+
}
64247
```
65248

66249
### **...**

0 commit comments

Comments
 (0)