From 5b558c06eac95c562e8e4362503383efde363370 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Wed, 20 May 2026 21:56:08 +0800 Subject: [PATCH] feat: add solutions for lc No.2657 --- .gitignore | 3 + README.md | 4 -- README_EN.md | 4 -- .../README.md | 59 +++++++++++++++++++ .../README_EN.md | 59 +++++++++++++++++++ .../Solution.rs | 16 +++++ .../Solution2.rs | 16 +++++ .../Solution3.rs | 12 ++++ .../README.md | 59 +++++++++++++------ 9 files changed, 207 insertions(+), 25 deletions(-) create mode 100644 solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution.rs create mode 100644 solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution2.rs create mode 100644 solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.rs diff --git a/.gitignore b/.gitignore index 3e3d375d726a1..3fd25e0ba7ab1 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,9 @@ package-lock.json !.cache/plugin/git-committers/ !.cache/plugin/git-committers/page-authors.json +# Claude +.claude/settings.local.json + # pnpm pnpm-lock.yaml .pnpm-store/ diff --git a/README.md b/README.md index 1b9d56c7f2d4b..f3c1374cd9641 100644 --- a/README.md +++ b/README.md @@ -173,10 +173,6 @@ - [找到最小生成树里的关键边和伪关键边](/solution/1400-1499/1489.Find%20Critical%20and%20Pseudo-Critical%20Edges%20in%20Minimum%20Spanning%20Tree/README.md) - `最小生成树`、`Kruskal 算法`、`并查集` - [判断二分图](/solution/0700-0799/0785.Is%20Graph%20Bipartite/README.md) - `染色法判定二分图`、`并查集` - - ## 加入我们 刷编程题的最大好处就是可以锻炼解决问题的思维能力。相信我,「如何去思考」​ 本身也是一项需要不断学习和练习的技能。非常感谢前微软工程师、现蚂蚁金服技术专家 [@kfstorm](https://github.com/kfstorm) 贡献了本项目的所有 [C# 题解](https://github.com/doocs/leetcode/pull/245)。 diff --git a/README_EN.md b/README_EN.md index 7b8b3f1a6fa38..c1cd3596d4e24 100644 --- a/README_EN.md +++ b/README_EN.md @@ -168,10 +168,6 @@ https://leetcode.doocs.org/en - [Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree](/solution/1400-1499/1489.Find%20Critical%20and%20Pseudo-Critical%20Edges%20in%20Minimum%20Spanning%20Tree/README_EN.md) - `Minimum Spanning Tree`, `Kruskal's algorithm`, `Union find` - [Is Graph Bipartite?](/solution/0700-0799/0785.Is%20Graph%20Bipartite/README_EN.md) - `Graph coloring`, `Union find` - - ## Contributions I'm looking for long-term contributors/partners to this repo! Send me [PRs](https://github.com/doocs/leetcode/pulls) if you're interested! See the following: diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README.md b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README.md index 113e96138ec9f..81a1bed8c7253 100644 --- a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README.md +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README.md @@ -174,6 +174,27 @@ function findThePrefixCommonArray(A: number[], B: number[]): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_the_prefix_common_array(a: Vec, b: Vec) -> Vec { + let n = a.len(); + let mut ans = vec![0; n]; + let mut cnt1 = vec![0; n + 1]; + let mut cnt2 = vec![0; n + 1]; + for i in 0..n { + cnt1[a[i] as usize] += 1; + cnt2[b[i] as usize] += 1; + for j in 1..=n { + ans[i] += std::cmp::min(cnt1[j], cnt2[j]); + } + } + ans + } +} +``` + @@ -296,6 +317,27 @@ function findThePrefixCommonArray(A: number[], B: number[]): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_the_prefix_common_array(a: Vec, b: Vec) -> Vec { + let n = a.len(); + let mut ans = vec![0; n]; + let mut vis = vec![1; n + 1]; + let mut s = 0; + for i in 0..n { + vis[a[i] as usize] ^= 1; + s += vis[a[i] as usize]; + vis[b[i] as usize] ^= 1; + s += vis[b[i] as usize]; + ans[i] = s; + } + ans + } +} +``` + @@ -403,6 +445,23 @@ function bitCount64(i: bigint): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_the_prefix_common_array(a: Vec, b: Vec) -> Vec { + let mut ans = Vec::with_capacity(a.len()); + let (mut x, mut y): (u64, u64) = (0, 0); + for (&a_val, &b_val) in a.iter().zip(b.iter()) { + x |= 1 << a_val; + y |= 1 << b_val; + ans.push((x & y).count_ones() as i32); + } + ans + } +} +``` + diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README_EN.md b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README_EN.md index 7a97ac75babca..ed42141759918 100644 --- a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README_EN.md +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/README_EN.md @@ -174,6 +174,27 @@ function findThePrefixCommonArray(A: number[], B: number[]): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_the_prefix_common_array(a: Vec, b: Vec) -> Vec { + let n = a.len(); + let mut ans = vec![0; n]; + let mut cnt1 = vec![0; n + 1]; + let mut cnt2 = vec![0; n + 1]; + for i in 0..n { + cnt1[a[i] as usize] += 1; + cnt2[b[i] as usize] += 1; + for j in 1..=n { + ans[i] += std::cmp::min(cnt1[j], cnt2[j]); + } + } + ans + } +} +``` + @@ -296,6 +317,27 @@ function findThePrefixCommonArray(A: number[], B: number[]): number[] { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_the_prefix_common_array(a: Vec, b: Vec) -> Vec { + let n = a.len(); + let mut ans = vec![0; n]; + let mut vis = vec![1; n + 1]; + let mut s = 0; + for i in 0..n { + vis[a[i] as usize] ^= 1; + s += vis[a[i] as usize]; + vis[b[i] as usize] ^= 1; + s += vis[b[i] as usize]; + ans[i] = s; + } + ans + } +} +``` + @@ -403,6 +445,23 @@ function bitCount64(i: bigint): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn find_the_prefix_common_array(a: Vec, b: Vec) -> Vec { + let mut ans = Vec::with_capacity(a.len()); + let (mut x, mut y): (u64, u64) = (0, 0); + for (&a_val, &b_val) in a.iter().zip(b.iter()) { + x |= 1 << a_val; + y |= 1 << b_val; + ans.push((x & y).count_ones() as i32); + } + ans + } +} +``` + diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution.rs b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution.rs new file mode 100644 index 0000000000000..10a33ecf019e1 --- /dev/null +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution.rs @@ -0,0 +1,16 @@ +impl Solution { + pub fn find_the_prefix_common_array(a: Vec, b: Vec) -> Vec { + let n = a.len(); + let mut ans = vec![0; n]; + let mut cnt1 = vec![0; n + 1]; + let mut cnt2 = vec![0; n + 1]; + for i in 0..n { + cnt1[a[i] as usize] += 1; + cnt2[b[i] as usize] += 1; + for j in 1..=n { + ans[i] += std::cmp::min(cnt1[j], cnt2[j]); + } + } + ans + } +} diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution2.rs b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution2.rs new file mode 100644 index 0000000000000..ddada9e8225bb --- /dev/null +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution2.rs @@ -0,0 +1,16 @@ +impl Solution { + pub fn find_the_prefix_common_array(a: Vec, b: Vec) -> Vec { + let n = a.len(); + let mut ans = vec![0; n]; + let mut vis = vec![1; n + 1]; + let mut s = 0; + for i in 0..n { + vis[a[i] as usize] ^= 1; + s += vis[a[i] as usize]; + vis[b[i] as usize] ^= 1; + s += vis[b[i] as usize]; + ans[i] = s; + } + ans + } +} diff --git a/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.rs b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.rs new file mode 100644 index 0000000000000..26878af489035 --- /dev/null +++ b/solution/2600-2699/2657.Find the Prefix Common Array of Two Arrays/Solution3.rs @@ -0,0 +1,12 @@ +impl Solution { + pub fn find_the_prefix_common_array(a: Vec, b: Vec) -> Vec { + let mut ans = Vec::with_capacity(a.len()); + let (mut x, mut y): (u64, u64) = (0, 0); + for (&a_val, &b_val) in a.iter().zip(b.iter()) { + x |= 1 << a_val; + y |= 1 << b_val; + ans.push((x & y).count_ones() as i32); + } + ans + } +} diff --git a/solution/3400-3499/3430.Maximum and Minimum Sums of at Most Size K Subarrays/README.md b/solution/3400-3499/3430.Maximum and Minimum Sums of at Most Size K Subarrays/README.md index eae9f235b3430..fbd2d4a3844d4 100644 --- a/solution/3400-3499/3430.Maximum and Minimum Sums of at Most Size K Subarrays/README.md +++ b/solution/3400-3499/3430.Maximum and Minimum Sums of at Most Size K Subarrays/README.md @@ -165,9 +165,11 @@ tags: ### 方法一:双 Deque 维护窗口最大值与最小值 + 本题要求计算所有长度不超过 $k$ 的子数组中: -* 子数组最大值之和 -* 子数组最小值之和 + +- 子数组最大值之和 +- 子数组最小值之和 并返回两者之和。 @@ -188,23 +190,28 @@ $$ 表示所有以索引 $i$ 结尾的合法子数组,它们各自最小值的总和。 接下来,我们维护两个单调队列: -* `max_stack`:维护当前窗口内所有子数组可能的最大值。 -* `min_stack`:维护当前窗口内所有子数组可能的最小值。 + +- `max_stack`:维护当前窗口内所有子数组可能的最大值。 +- `min_stack`:维护当前窗口内所有子数组可能的最小值。 虽然底层数据结构为 `deque`,但由于绝大多数操作都发生在右侧,因此其本质仍然是单调栈。 队列中的每个元素格式为: + ```text (index, value, shares) ``` 其中: -* `index`:元素索引 -* `value`:元素值 -* `shares`:该元素在当前窗口内,作为子数组最大值 / 最小值的贡献次数 + +- `index`:元素索引 +- `value`:元素值 +- `shares`:该元素在当前窗口内,作为子数组最大值 / 最小值的贡献次数 --- + #### Step 1. 边界管理 + 当遍历到当前元素 `nums[i]` 时,我们首先需要确保窗口长度不超过 $k$。 窗口左边界为: @@ -216,17 +223,21 @@ $$ 若某元素索引已经小于该边界,说明其已经离开窗口,不再属于任何合法子数组。 因此: -* `max_stack` 栈头元素若已越界,则弹出 -* `min_stack` 栈头元素若已越界,则弹出 + +- `max_stack` 栈头元素若已越界,则弹出 +- `min_stack` 栈头元素若已越界,则弹出 同时,需要从: -* `subarrays_max_sum` -* `subarrays_min_sum` + +- `subarrays_max_sum` +- `subarrays_min_sum` 中扣除这些元素对应的贡献。 --- + #### Step 2. 更新单调栈 + 对于当前元素 `nums[i]`: 若 `max_stack` 栈尾元素的值小于等于 `nums[i]`: @@ -234,16 +245,19 @@ $$ 说明这些元素已经不可能继续成为后续子数组的最大值。 因此: + 1. 持续弹出这些元素 2. 将它们的贡献次数 `shares` 转移给 `nums[i]` 3. 更新 `subarrays_max_sum` 若弹出的元素为: + ```text (prev_idx, prev_num, prev_shares) ``` 则会对: + ```text subarrays_max_sum ``` @@ -259,43 +273,54 @@ $$ 随后,再加上当前元素自身形成的新子数组贡献。 最后,将: + ```text (i, nums[i], shares) ``` + 压入 `max_stack`。 --- + `min_stack` 的操作方式完全相同。区别仅在于: -* `max_stack` 维护单调递减性质 -* `min_stack` 维护单调递增性质 + +- `max_stack` 维护单调递减性质 +- `min_stack` 维护单调递增性质 因此比较条件需要反转: + ```text max_stack: top_value <= nums[i] min_stack: top_value >= nums[i] ``` --- + #### Step 3. 累加答案 + 当索引 $i$ 处理完成后: -* `subarrays_max_sum` +- `subarrays_max_sum` 表示所有以 $i$ 结尾的合法子数组最大值总和 -* `subarrays_min_sum` +- `subarrays_min_sum` 表示所有以 $i$ 结尾的合法子数组最小值总和 因此我们将两者加入最终答案: + ```text subarrays_max_min_sum ``` + 最终返回该结果即可。 --- + 时间复杂度为 $O(n)$,空间复杂度为 $O(n)$。 这是因为: -* 每个元素至多进入并离开 `max_stack` 各一次 -* 每个元素至多进入并离开 `min_stack` 各一次 + +- 每个元素至多进入并离开 `max_stack` 各一次 +- 每个元素至多进入并离开 `min_stack` 各一次 因此每个元素总操作次数不超过四次,整体时间复杂度为严格线性时间复杂度。