Skip to content

Commit 67e2be0

Browse files
authored
feat: add solutions to lc problem: No.2476,2478 (#2371)
* No.2476.Closest Nodes Queries in a Binary Search Tree * No.2478.Number of Beautiful Partitions
1 parent d6ef9d3 commit 67e2be0

File tree

8 files changed

+248
-18
lines changed

8 files changed

+248
-18
lines changed

solution/2400-2499/2476.Closest Nodes Queries in a Binary Search Tree/README.md

+44-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262

6363
由于题目中给出的是一棵二叉搜索树,因此我们可以通过中序遍历得到一个有序数组,然后对于每个查询,我们可以通过二分查找得到小于等于该查询值的最大值和大于等于该查询值的最小值。
6464

65-
时间复杂度 $O(n + m \times \log n)$,空间复杂度 $O(n)。其中 $n$ 和 $m$ 分别是二叉搜索树中的节点数和查询数。
65+
时间复杂度 $O(n + m \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是二叉搜索树中的节点数和查询数。
6666

6767
<!-- tabs:start -->
6868

@@ -267,6 +267,49 @@ function closestNodes(root: TreeNode | null, queries: number[]): number[][] {
267267
}
268268
```
269269

270+
```cs
271+
/**
272+
* Definition for a binary tree node.
273+
* public class TreeNode {
274+
* public int val;
275+
* public TreeNode left;
276+
* public TreeNode right;
277+
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
278+
* this.val = val;
279+
* this.left = left;
280+
* this.right = right;
281+
* }
282+
* }
283+
*/
284+
public class Solution {
285+
private List<int> nums = new List<int>();
286+
287+
public IList<IList<int>> ClosestNodes(TreeNode root, IList<int> queries) {
288+
Dfs(root);
289+
List<IList<int>> ans = new List<IList<int>>();
290+
foreach (int x in queries) {
291+
int i = nums.BinarySearch(x + 1);
292+
int j = nums.BinarySearch(x);
293+
i = i < 0 ? -i - 2 : i - 1;
294+
j = j < 0 ? -j - 1 : j;
295+
int mi = i >= 0 && i < nums.Count ? nums[i] : -1;
296+
int mx = j >= 0 && j < nums.Count ? nums[j] : -1;
297+
ans.Add(new List<int> {mi, mx});
298+
}
299+
return ans;
300+
}
301+
302+
private void Dfs(TreeNode root) {
303+
if (root == null) {
304+
return;
305+
}
306+
Dfs(root.left);
307+
nums.Add(root.val);
308+
Dfs(root.right);
309+
}
310+
}
311+
```
312+
270313
<!-- tabs:end -->
271314

272315
<!-- end -->

solution/2400-2499/2476.Closest Nodes Queries in a Binary Search Tree/README_EN.md

+43
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,49 @@ function closestNodes(root: TreeNode | null, queries: number[]): number[][] {
259259
}
260260
```
261261

262+
```cs
263+
/**
264+
* Definition for a binary tree node.
265+
* public class TreeNode {
266+
* public int val;
267+
* public TreeNode left;
268+
* public TreeNode right;
269+
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
270+
* this.val = val;
271+
* this.left = left;
272+
* this.right = right;
273+
* }
274+
* }
275+
*/
276+
public class Solution {
277+
private List<int> nums = new List<int>();
278+
279+
public IList<IList<int>> ClosestNodes(TreeNode root, IList<int> queries) {
280+
Dfs(root);
281+
List<IList<int>> ans = new List<IList<int>>();
282+
foreach (int x in queries) {
283+
int i = nums.BinarySearch(x + 1);
284+
int j = nums.BinarySearch(x);
285+
i = i < 0 ? -i - 2 : i - 1;
286+
j = j < 0 ? -j - 1 : j;
287+
int mi = i >= 0 && i < nums.Count ? nums[i] : -1;
288+
int mx = j >= 0 && j < nums.Count ? nums[j] : -1;
289+
ans.Add(new List<int> {mi, mx});
290+
}
291+
return ans;
292+
}
293+
294+
private void Dfs(TreeNode root) {
295+
if (root == null) {
296+
return;
297+
}
298+
Dfs(root.left);
299+
nums.Add(root.val);
300+
Dfs(root.right);
301+
}
302+
}
303+
```
304+
262305
<!-- tabs:end -->
263306

264307
<!-- end -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* public class TreeNode {
4+
* public int val;
5+
* public TreeNode left;
6+
* public TreeNode right;
7+
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
8+
* this.val = val;
9+
* this.left = left;
10+
* this.right = right;
11+
* }
12+
* }
13+
*/
14+
public class Solution {
15+
private List<int> nums = new List<int>();
16+
17+
public IList<IList<int>> ClosestNodes(TreeNode root, IList<int> queries) {
18+
Dfs(root);
19+
List<IList<int>> ans = new List<IList<int>>();
20+
foreach (int x in queries) {
21+
int i = nums.BinarySearch(x + 1);
22+
int j = nums.BinarySearch(x);
23+
i = i < 0 ? -i - 2 : i - 1;
24+
j = j < 0 ? -j - 1 : j;
25+
int mi = i >= 0 && i < nums.Count ? nums[i] : -1;
26+
int mx = j >= 0 && j < nums.Count ? nums[j] : -1;
27+
ans.Add(new List<int> {mi, mx});
28+
}
29+
return ans;
30+
}
31+
32+
private void Dfs(TreeNode root) {
33+
if (root == null) {
34+
return;
35+
}
36+
Dfs(root.left);
37+
nums.Add(root.val);
38+
Dfs(root.right);
39+
}
40+
}

solution/2400-2499/2478.Number of Beautiful Partitions/README.md

+34-6
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464

6565
### 方法一:动态规划
6666

67-
定义 $f[i][j]$ 表示前 $i$ 个字符分割成 $j$ 段的方案数。初始化 $f[0][0] = 1$,其余 $f[i][j] = 0$。
67+
我们定义 $f[i][j]$ 表示前 $i$ 个字符分割成 $j$ 段的方案数。初始化 $f[0][0] = 1$,其余 $f[i][j] = 0$。
6868

6969
首先,我们需要判断第 $i$ 个字符是否能成为第 $j$ 段的最后一个字符,它需要同时满足以下条件:
7070

@@ -111,8 +111,6 @@ class Solution:
111111

112112
```java
113113
class Solution {
114-
private static final int MOD = (int) 1e9 + 7;
115-
116114
public int beautifulPartitions(String s, int k, int minLength) {
117115
int n = s.length();
118116
if (!prime(s.charAt(0)) || prime(s.charAt(n - 1))) {
@@ -122,14 +120,15 @@ class Solution {
122120
int[][] g = new int[n + 1][k + 1];
123121
f[0][0] = 1;
124122
g[0][0] = 1;
123+
final int mod = (int) 1e9 + 7;
125124
for (int i = 1; i <= n; ++i) {
126125
if (i >= minLength && !prime(s.charAt(i - 1)) && (i == n || prime(s.charAt(i)))) {
127126
for (int j = 1; j <= k; ++j) {
128127
f[i][j] = g[i - minLength][j - 1];
129128
}
130129
}
131130
for (int j = 0; j <= k; ++j) {
132-
g[i][j] = (g[i - 1][j] + f[i][j]) % MOD;
131+
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
133132
}
134133
}
135134
return f[n][k];
@@ -144,8 +143,6 @@ class Solution {
144143
```cpp
145144
class Solution {
146145
public:
147-
const int mod = 1e9 + 7;
148-
149146
int beautifulPartitions(string s, int k, int minLength) {
150147
int n = s.size();
151148
auto prime = [](char c) {
@@ -155,6 +152,7 @@ public:
155152
vector<vector<int>> f(n + 1, vector<int>(k + 1));
156153
vector<vector<int>> g(n + 1, vector<int>(k + 1));
157154
f[0][0] = g[0][0] = 1;
155+
const int mod = 1e9 + 7;
158156
for (int i = 1; i <= n; ++i) {
159157
if (i >= minLength && !prime(s[i - 1]) && (i == n || prime(s[i]))) {
160158
for (int j = 1; j <= k; ++j) {
@@ -201,6 +199,36 @@ func beautifulPartitions(s string, k int, minLength int) int {
201199
}
202200
```
203201

202+
```ts
203+
function beautifulPartitions(s: string, k: number, minLength: number): number {
204+
const prime = (c: string): boolean => {
205+
return c === '2' || c === '3' || c === '5' || c === '7';
206+
};
207+
208+
const n: number = s.length;
209+
if (!prime(s[0]) || prime(s[n - 1])) return 0;
210+
211+
const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0));
212+
const g: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0));
213+
const mod: number = 1e9 + 7;
214+
215+
f[0][0] = g[0][0] = 1;
216+
217+
for (let i = 1; i <= n; ++i) {
218+
if (i >= minLength && !prime(s[i - 1]) && (i === n || prime(s[i]))) {
219+
for (let j = 1; j <= k; ++j) {
220+
f[i][j] = g[i - minLength][j - 1];
221+
}
222+
}
223+
for (let j = 0; j <= k; ++j) {
224+
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
225+
}
226+
}
227+
228+
return f[n][k];
229+
}
230+
```
231+
204232
<!-- tabs:end -->
205233

206234
<!-- end -->

solution/2400-2499/2478.Number of Beautiful Partitions/README_EN.md

+57-6
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,30 @@
5858

5959
## Solutions
6060

61-
### Solution 1
61+
### Solution 1: Dynamic Programming
62+
63+
We define $f[i][j]$ as the number of schemes for dividing the first $i$ characters into $j$ sections. Initialize $f[0][0] = 1$, and the rest $f[i][j] = 0$.
64+
65+
First, we need to determine whether the $i$th character can be the last character of the $j$th section, it needs to meet the following conditions simultaneously:
66+
67+
1. The $i$th character is a non-prime number;
68+
1. The $i+1$th character is a prime number, or the $i$th character is the last character of the entire string.
69+
70+
If the $i$th character cannot be the last character of the $j$th section, then $f[i][j]=0$. Otherwise, we have:
71+
72+
$$
73+
f[i][j]=\sum_{t=0}^{i-minLength}f[t][j-1]
74+
$$
75+
76+
That is to say, we need to enumerate which character is the end of the previous section. Here we use the prefix sum array $g[i][j] = \sum_{t=0}^{i}f[t][j]$ to optimize the time complexity of enumeration.
77+
78+
Then we have:
79+
80+
$$
81+
f[i][j]=g[i-minLength][j-1]
82+
$$
83+
84+
The time complexity is $O(n \times k)$, and the space complexity is $O(n \times k)$. Where $n$ and $k$ are the length of the string $s$ and the number of sections to be divided, respectively.
6285

6386
<!-- tabs:start -->
6487

@@ -84,8 +107,6 @@ class Solution:
84107

85108
```java
86109
class Solution {
87-
private static final int MOD = (int) 1e9 + 7;
88-
89110
public int beautifulPartitions(String s, int k, int minLength) {
90111
int n = s.length();
91112
if (!prime(s.charAt(0)) || prime(s.charAt(n - 1))) {
@@ -95,14 +116,15 @@ class Solution {
95116
int[][] g = new int[n + 1][k + 1];
96117
f[0][0] = 1;
97118
g[0][0] = 1;
119+
final int mod = (int) 1e9 + 7;
98120
for (int i = 1; i <= n; ++i) {
99121
if (i >= minLength && !prime(s.charAt(i - 1)) && (i == n || prime(s.charAt(i)))) {
100122
for (int j = 1; j <= k; ++j) {
101123
f[i][j] = g[i - minLength][j - 1];
102124
}
103125
}
104126
for (int j = 0; j <= k; ++j) {
105-
g[i][j] = (g[i - 1][j] + f[i][j]) % MOD;
127+
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
106128
}
107129
}
108130
return f[n][k];
@@ -117,8 +139,6 @@ class Solution {
117139
```cpp
118140
class Solution {
119141
public:
120-
const int mod = 1e9 + 7;
121-
122142
int beautifulPartitions(string s, int k, int minLength) {
123143
int n = s.size();
124144
auto prime = [](char c) {
@@ -128,6 +148,7 @@ public:
128148
vector<vector<int>> f(n + 1, vector<int>(k + 1));
129149
vector<vector<int>> g(n + 1, vector<int>(k + 1));
130150
f[0][0] = g[0][0] = 1;
151+
const int mod = 1e9 + 7;
131152
for (int i = 1; i <= n; ++i) {
132153
if (i >= minLength && !prime(s[i - 1]) && (i == n || prime(s[i]))) {
133154
for (int j = 1; j <= k; ++j) {
@@ -174,6 +195,36 @@ func beautifulPartitions(s string, k int, minLength int) int {
174195
}
175196
```
176197

198+
```ts
199+
function beautifulPartitions(s: string, k: number, minLength: number): number {
200+
const prime = (c: string): boolean => {
201+
return c === '2' || c === '3' || c === '5' || c === '7';
202+
};
203+
204+
const n: number = s.length;
205+
if (!prime(s[0]) || prime(s[n - 1])) return 0;
206+
207+
const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0));
208+
const g: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0));
209+
const mod: number = 1e9 + 7;
210+
211+
f[0][0] = g[0][0] = 1;
212+
213+
for (let i = 1; i <= n; ++i) {
214+
if (i >= minLength && !prime(s[i - 1]) && (i === n || prime(s[i]))) {
215+
for (let j = 1; j <= k; ++j) {
216+
f[i][j] = g[i - minLength][j - 1];
217+
}
218+
}
219+
for (let j = 0; j <= k; ++j) {
220+
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
221+
}
222+
}
223+
224+
return f[n][k];
225+
}
226+
```
227+
177228
<!-- tabs:end -->
178229

179230
<!-- end -->

solution/2400-2499/2478.Number of Beautiful Partitions/Solution.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
class Solution {
22
public:
3-
const int mod = 1e9 + 7;
4-
53
int beautifulPartitions(string s, int k, int minLength) {
64
int n = s.size();
75
auto prime = [](char c) {
@@ -11,6 +9,7 @@ class Solution {
119
vector<vector<int>> f(n + 1, vector<int>(k + 1));
1210
vector<vector<int>> g(n + 1, vector<int>(k + 1));
1311
f[0][0] = g[0][0] = 1;
12+
const int mod = 1e9 + 7;
1413
for (int i = 1; i <= n; ++i) {
1514
if (i >= minLength && !prime(s[i - 1]) && (i == n || prime(s[i]))) {
1615
for (int j = 1; j <= k; ++j) {

solution/2400-2499/2478.Number of Beautiful Partitions/Solution.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
class Solution {
2-
private static final int MOD = (int) 1e9 + 7;
3-
42
public int beautifulPartitions(String s, int k, int minLength) {
53
int n = s.length();
64
if (!prime(s.charAt(0)) || prime(s.charAt(n - 1))) {
@@ -10,14 +8,15 @@ public int beautifulPartitions(String s, int k, int minLength) {
108
int[][] g = new int[n + 1][k + 1];
119
f[0][0] = 1;
1210
g[0][0] = 1;
11+
final int mod = (int) 1e9 + 7;
1312
for (int i = 1; i <= n; ++i) {
1413
if (i >= minLength && !prime(s.charAt(i - 1)) && (i == n || prime(s.charAt(i)))) {
1514
for (int j = 1; j <= k; ++j) {
1615
f[i][j] = g[i - minLength][j - 1];
1716
}
1817
}
1918
for (int j = 0; j <= k; ++j) {
20-
g[i][j] = (g[i - 1][j] + f[i][j]) % MOD;
19+
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
2120
}
2221
}
2322
return f[n][k];

0 commit comments

Comments
 (0)