Skip to content

feat: add solutions to lc problem: No.2476,2478 #2371

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@

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

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

<!-- tabs:start -->

Expand Down Expand Up @@ -267,6 +267,49 @@ function closestNodes(root: TreeNode | null, queries: number[]): number[][] {
}
```

```cs
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
public class Solution {
private List<int> nums = new List<int>();

public IList<IList<int>> ClosestNodes(TreeNode root, IList<int> queries) {
Dfs(root);
List<IList<int>> ans = new List<IList<int>>();
foreach (int x in queries) {
int i = nums.BinarySearch(x + 1);
int j = nums.BinarySearch(x);
i = i < 0 ? -i - 2 : i - 1;
j = j < 0 ? -j - 1 : j;
int mi = i >= 0 && i < nums.Count ? nums[i] : -1;
int mx = j >= 0 && j < nums.Count ? nums[j] : -1;
ans.Add(new List<int> {mi, mx});
}
return ans;
}

private void Dfs(TreeNode root) {
if (root == null) {
return;
}
Dfs(root.left);
nums.Add(root.val);
Dfs(root.right);
}
}
```

<!-- tabs:end -->

<!-- end -->
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,49 @@ function closestNodes(root: TreeNode | null, queries: number[]): number[][] {
}
```

```cs
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
public class Solution {
private List<int> nums = new List<int>();

public IList<IList<int>> ClosestNodes(TreeNode root, IList<int> queries) {
Dfs(root);
List<IList<int>> ans = new List<IList<int>>();
foreach (int x in queries) {
int i = nums.BinarySearch(x + 1);
int j = nums.BinarySearch(x);
i = i < 0 ? -i - 2 : i - 1;
j = j < 0 ? -j - 1 : j;
int mi = i >= 0 && i < nums.Count ? nums[i] : -1;
int mx = j >= 0 && j < nums.Count ? nums[j] : -1;
ans.Add(new List<int> {mi, mx});
}
return ans;
}

private void Dfs(TreeNode root) {
if (root == null) {
return;
}
Dfs(root.left);
nums.Add(root.val);
Dfs(root.right);
}
}
```

<!-- tabs:end -->

<!-- end -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
public class Solution {
private List<int> nums = new List<int>();

public IList<IList<int>> ClosestNodes(TreeNode root, IList<int> queries) {
Dfs(root);
List<IList<int>> ans = new List<IList<int>>();
foreach (int x in queries) {
int i = nums.BinarySearch(x + 1);
int j = nums.BinarySearch(x);
i = i < 0 ? -i - 2 : i - 1;
j = j < 0 ? -j - 1 : j;
int mi = i >= 0 && i < nums.Count ? nums[i] : -1;
int mx = j >= 0 && j < nums.Count ? nums[j] : -1;
ans.Add(new List<int> {mi, mx});
}
return ans;
}

private void Dfs(TreeNode root) {
if (root == null) {
return;
}
Dfs(root.left);
nums.Add(root.val);
Dfs(root.right);
}
}
40 changes: 34 additions & 6 deletions solution/2400-2499/2478.Number of Beautiful Partitions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

### 方法一:动态规划

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

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

Expand Down Expand Up @@ -111,8 +111,6 @@ class Solution:

```java
class Solution {
private static final int MOD = (int) 1e9 + 7;

public int beautifulPartitions(String s, int k, int minLength) {
int n = s.length();
if (!prime(s.charAt(0)) || prime(s.charAt(n - 1))) {
Expand All @@ -122,14 +120,15 @@ class Solution {
int[][] g = new int[n + 1][k + 1];
f[0][0] = 1;
g[0][0] = 1;
final int mod = (int) 1e9 + 7;
for (int i = 1; i <= n; ++i) {
if (i >= minLength && !prime(s.charAt(i - 1)) && (i == n || prime(s.charAt(i)))) {
for (int j = 1; j <= k; ++j) {
f[i][j] = g[i - minLength][j - 1];
}
}
for (int j = 0; j <= k; ++j) {
g[i][j] = (g[i - 1][j] + f[i][j]) % MOD;
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
}
}
return f[n][k];
Expand All @@ -144,8 +143,6 @@ class Solution {
```cpp
class Solution {
public:
const int mod = 1e9 + 7;

int beautifulPartitions(string s, int k, int minLength) {
int n = s.size();
auto prime = [](char c) {
Expand All @@ -155,6 +152,7 @@ public:
vector<vector<int>> f(n + 1, vector<int>(k + 1));
vector<vector<int>> g(n + 1, vector<int>(k + 1));
f[0][0] = g[0][0] = 1;
const int mod = 1e9 + 7;
for (int i = 1; i <= n; ++i) {
if (i >= minLength && !prime(s[i - 1]) && (i == n || prime(s[i]))) {
for (int j = 1; j <= k; ++j) {
Expand Down Expand Up @@ -201,6 +199,36 @@ func beautifulPartitions(s string, k int, minLength int) int {
}
```

```ts
function beautifulPartitions(s: string, k: number, minLength: number): number {
const prime = (c: string): boolean => {
return c === '2' || c === '3' || c === '5' || c === '7';
};

const n: number = s.length;
if (!prime(s[0]) || prime(s[n - 1])) return 0;

const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0));
const g: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0));
const mod: number = 1e9 + 7;

f[0][0] = g[0][0] = 1;

for (let i = 1; i <= n; ++i) {
if (i >= minLength && !prime(s[i - 1]) && (i === n || prime(s[i]))) {
for (let j = 1; j <= k; ++j) {
f[i][j] = g[i - minLength][j - 1];
}
}
for (let j = 0; j <= k; ++j) {
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
}
}

return f[n][k];
}
```

<!-- tabs:end -->

<!-- end -->
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,30 @@

## Solutions

### Solution 1
### Solution 1: Dynamic Programming

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$.

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:

1. The $i$th character is a non-prime number;
1. The $i+1$th character is a prime number, or the $i$th character is the last character of the entire string.

If the $i$th character cannot be the last character of the $j$th section, then $f[i][j]=0$. Otherwise, we have:

$$
f[i][j]=\sum_{t=0}^{i-minLength}f[t][j-1]
$$

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.

Then we have:

$$
f[i][j]=g[i-minLength][j-1]
$$

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.

<!-- tabs:start -->

Expand All @@ -84,8 +107,6 @@ class Solution:

```java
class Solution {
private static final int MOD = (int) 1e9 + 7;

public int beautifulPartitions(String s, int k, int minLength) {
int n = s.length();
if (!prime(s.charAt(0)) || prime(s.charAt(n - 1))) {
Expand All @@ -95,14 +116,15 @@ class Solution {
int[][] g = new int[n + 1][k + 1];
f[0][0] = 1;
g[0][0] = 1;
final int mod = (int) 1e9 + 7;
for (int i = 1; i <= n; ++i) {
if (i >= minLength && !prime(s.charAt(i - 1)) && (i == n || prime(s.charAt(i)))) {
for (int j = 1; j <= k; ++j) {
f[i][j] = g[i - minLength][j - 1];
}
}
for (int j = 0; j <= k; ++j) {
g[i][j] = (g[i - 1][j] + f[i][j]) % MOD;
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
}
}
return f[n][k];
Expand All @@ -117,8 +139,6 @@ class Solution {
```cpp
class Solution {
public:
const int mod = 1e9 + 7;

int beautifulPartitions(string s, int k, int minLength) {
int n = s.size();
auto prime = [](char c) {
Expand All @@ -128,6 +148,7 @@ public:
vector<vector<int>> f(n + 1, vector<int>(k + 1));
vector<vector<int>> g(n + 1, vector<int>(k + 1));
f[0][0] = g[0][0] = 1;
const int mod = 1e9 + 7;
for (int i = 1; i <= n; ++i) {
if (i >= minLength && !prime(s[i - 1]) && (i == n || prime(s[i]))) {
for (int j = 1; j <= k; ++j) {
Expand Down Expand Up @@ -174,6 +195,36 @@ func beautifulPartitions(s string, k int, minLength int) int {
}
```

```ts
function beautifulPartitions(s: string, k: number, minLength: number): number {
const prime = (c: string): boolean => {
return c === '2' || c === '3' || c === '5' || c === '7';
};

const n: number = s.length;
if (!prime(s[0]) || prime(s[n - 1])) return 0;

const f: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0));
const g: number[][] = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0));
const mod: number = 1e9 + 7;

f[0][0] = g[0][0] = 1;

for (let i = 1; i <= n; ++i) {
if (i >= minLength && !prime(s[i - 1]) && (i === n || prime(s[i]))) {
for (let j = 1; j <= k; ++j) {
f[i][j] = g[i - minLength][j - 1];
}
}
for (let j = 0; j <= k; ++j) {
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
}
}

return f[n][k];
}
```

<!-- tabs:end -->

<!-- end -->
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
class Solution {
public:
const int mod = 1e9 + 7;

int beautifulPartitions(string s, int k, int minLength) {
int n = s.size();
auto prime = [](char c) {
Expand All @@ -11,6 +9,7 @@ class Solution {
vector<vector<int>> f(n + 1, vector<int>(k + 1));
vector<vector<int>> g(n + 1, vector<int>(k + 1));
f[0][0] = g[0][0] = 1;
const int mod = 1e9 + 7;
for (int i = 1; i <= n; ++i) {
if (i >= minLength && !prime(s[i - 1]) && (i == n || prime(s[i]))) {
for (int j = 1; j <= k; ++j) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
class Solution {
private static final int MOD = (int) 1e9 + 7;

public int beautifulPartitions(String s, int k, int minLength) {
int n = s.length();
if (!prime(s.charAt(0)) || prime(s.charAt(n - 1))) {
Expand All @@ -10,14 +8,15 @@ public int beautifulPartitions(String s, int k, int minLength) {
int[][] g = new int[n + 1][k + 1];
f[0][0] = 1;
g[0][0] = 1;
final int mod = (int) 1e9 + 7;
for (int i = 1; i <= n; ++i) {
if (i >= minLength && !prime(s.charAt(i - 1)) && (i == n || prime(s.charAt(i)))) {
for (int j = 1; j <= k; ++j) {
f[i][j] = g[i - minLength][j - 1];
}
}
for (int j = 0; j <= k; ++j) {
g[i][j] = (g[i - 1][j] + f[i][j]) % MOD;
g[i][j] = (g[i - 1][j] + f[i][j]) % mod;
}
}
return f[n][k];
Expand Down
Loading