Skip to content

feat: add solutions to lc problem: No.2106 #4614

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
Aug 3, 2025
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 @@ -83,24 +83,24 @@ tags:

### 方法一:双指针

我们不妨假设移动的位置区间为 $[l,r]$,开始位置为 $startPos$,来看看如何算出移动的最小步数。根据 $startPos$ 所处的位置,我们可以分为三种情况:
我们不妨假设移动的位置区间为 $[l, r]$,开始位置为 $\textit{startPos}$,来看看如何算出移动的最小步数。根据 $\textit{startPos}$ 所处的位置,我们可以分为三种情况:

1. 如果 $startPos \leq l$,那么就是从 $startPos$ 一直向右移动到 $r$。移动的最小步数为 $r - startPos$;
2. 如果 $startPos \geq r$,那么就是从 $startPos$ 一直向左移动到 $l$。移动的最小步数为 $startPos - l$;
3. 如果 $l \lt startPos \lt r$,那么可以从 $startPos$ 向左移动到 $l$,再向右移动到 $r$;也可以从 $startPos$ 向右移动到 $r$,再向左移动到 $l$。移动的最小步数为 $r - l + \min(\lvert startPos - l \rvert, \lvert r - startPos \rvert)$。
1. 如果 $\textit{startPos} \leq l$,那么就是从 $\textit{startPos}$ 一直向右移动到 $r$。移动的最小步数为 $r - \textit{startPos}$;
2. 如果 $\textit{startPos} \geq r$,那么就是从 $\textit{startPos}$ 一直向左移动到 $l$。移动的最小步数为 $\textit{startPos} - l$;
3. 如果 $l < \textit{startPos} < r$,那么可以从 $\textit{startPos}$ 向左移动到 $l$,再向右移动到 $r$;也可以从 $\textit{startPos}$ 向右移动到 $r$,再向左移动到 $l$。移动的最小步数为 $r - l + \min(\lvert \textit{startPos} - l \rvert, \lvert r - \textit{startPos} \rvert)$。

以上三种情况可以统一用式子 $r - l + \min(\lvert startPos - l \rvert, \lvert r - startPos \rvert)$ 表示。
以上三种情况可以统一用式子 $r - l + \min(\lvert \textit{startPos} - l \rvert, \lvert r - \textit{startPos} \rvert)$ 表示。

假设我们固定区间右端点 $r$,向右移动左端点 $l$,我们来看看最小移动步数是怎么变化的。

1. 如果 $startPos \leq l$,随着 $l$ 的增大,最小步数不会发生变化。
2. 如果 $startPos \gt l$,随着 $l$ 的增大,最小步数会减小。
1. 如果 $\textit{startPos} \leq l$,随着 $l$ 的增大,最小步数不会发生变化。
2. 如果 $\textit{startPos} > l$,随着 $l$ 的增大,最小步数会减小。

因此,随着 $l$ 的增大,最小移动步数一定是非严格单调递减的。基于此,我们可以使用双指针的方法,找出所有符合条件的最大区间,然后取所有符合条件的区间中水果总数最大的一个作为答案。

具体地,我们用两个指针 $i$ 和 $j$ 分别指向区间的左右下标,初始时 $i = j = 0$。另外用一个变量 $s$ 记录区间内的水果总数,初始时 $s = 0$。

每次我们将 $j$ 加入区间中,然后更新 $s = s + fruits[j][1]$。如果此时区间内的最小步数 $fruits[j][0] - fruits[i][0] + \min(\lvert startPos - fruits[i][0] \rvert, \lvert startPos - fruits[j][0] \rvert)$ 大于 $k$,那么我们就将 $i$ 循环向右移动,直到 $i \gt j$ 或者区间内的最小步数小于等于 $k$。此时我们更新答案 $ans = \max(ans, s)$。继续移动 $j$,直到 $j$ 到达数组末尾。
每次我们将 $j$ 加入区间中,然后更新 $s = s + \textit{fruits}[j][1]$。如果此时区间内的最小步数 $\textit{fruits}[j][0] - \textit{fruits}[i][0] + \min(\lvert \textit{startPos} - \textit{fruits}[i][0] \rvert, \lvert \textit{startPos} - \textit{fruits}[j][0] \rvert)$ 大于 $k$,那么我们就将 $i$ 循环向右移动,直到 $i > j$ 或者区间内的最小步数小于等于 $k$。此时我们更新答案 $\textit{ans} = \max(\textit{ans}, s)$。继续移动 $j$,直到 $j$ 到达数组末尾。

最后返回答案即可。

Expand Down Expand Up @@ -219,6 +219,29 @@ function maxTotalFruits(fruits: number[][], startPos: number, k: number): number
}
```

#### Rust

```rust
impl Solution {
pub fn max_total_fruits(fruits: Vec<Vec<i32>>, start_pos: i32, k: i32) -> i32 {
let mut ans = 0;
let mut s = 0;
let mut i = 0;
for j in 0..fruits.len() {
let pj = fruits[j][0];
let fj = fruits[j][1];
s += fj;
while i <= j && pj - fruits[i][0] + std::cmp::min((start_pos - fruits[i][0]).abs(), (start_pos - pj).abs()) > k {
s -= fruits[i][1];
i += 1;
}
ans = ans.max(s)
}
ans
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ tags:
<pre>
<strong>Input:</strong> fruits = [[2,8],[6,3],[8,6]], startPos = 5, k = 4
<strong>Output:</strong> 9
<strong>Explanation:</strong>
<strong>Explanation:</strong>
The optimal way is to:
- Move right to position 6 and harvest 3 fruits
- Move right to position 8 and harvest 6 fruits
Expand All @@ -45,7 +45,7 @@ You moved 3 steps and harvested 3 + 6 = 9 fruits in total.
<pre>
<strong>Input:</strong> fruits = [[0,9],[4,1],[5,7],[6,2],[7,4],[10,9]], startPos = 5, k = 4
<strong>Output:</strong> 14
<strong>Explanation:</strong>
<strong>Explanation:</strong>
You can move at most k = 4 steps, so you cannot reach position 0 nor 10.
The optimal way is to:
- Harvest the 7 fruits at the starting position 5
Expand Down Expand Up @@ -82,7 +82,30 @@ You can move at most k = 2 steps and cannot reach any position with fruits.

<!-- solution:start -->

### Solution 1
### Solution 1: Two Pointers

Let's assume the movement range is $[l, r]$ and the starting position is $\textit{startPos}$. We need to calculate the minimum number of steps required. Based on the position of $\textit{startPos}$, we can divide this into three cases:

1. If $\textit{startPos} \leq l$, then we move right from $\textit{startPos}$ to $r$. The minimum number of steps is $r - \textit{startPos}$;
2. If $\textit{startPos} \geq r$, then we move left from $\textit{startPos}$ to $l$. The minimum number of steps is $\textit{startPos} - l$;
3. If $l < \textit{startPos} < r$, we can either move left from $\textit{startPos}$ to $l$ then right to $r$, or move right from $\textit{startPos}$ to $r$ then left to $l$. The minimum number of steps is $r - l + \min(\lvert \textit{startPos} - l \rvert, \lvert r - \textit{startPos} \rvert)$.

All three cases can be unified by the formula $r - l + \min(\lvert \textit{startPos} - l \rvert, \lvert r - \textit{startPos} \rvert)$.

Suppose we fix the right endpoint $r$ of the interval and move the left endpoint $l$ to the right. Let's see how the minimum number of steps changes:

1. If $\textit{startPos} \leq l$, as $l$ increases, the minimum number of steps remains unchanged.
2. If $\textit{startPos} > l$, as $l$ increases, the minimum number of steps decreases.

Therefore, as $l$ increases, the minimum number of steps is non-strictly monotonically decreasing. Based on this, we can use the two-pointer approach to find all qualifying maximum intervals, then take the one with the maximum total fruits among all qualifying intervals as the answer.

Specifically, we use two pointers $i$ and $j$ to point to the left and right indices of the interval, initially $i = j = 0$. We also use a variable $s$ to record the total number of fruits in the interval, initially $s = 0$.

Each time we include $j$ in the interval, then update $s = s + \textit{fruits}[j][1]$. If the minimum number of steps in the current interval $\textit{fruits}[j][0] - \textit{fruits}[i][0] + \min(\lvert \textit{startPos} - \textit{fruits}[i][0] \rvert, \lvert \textit{startPos} - \textit{fruits}[j][0] \rvert)$ is greater than $k$, we move $i$ to the right in a loop until $i > j$ or the minimum number of steps in the interval is less than or equal to $k$. At this point, we update the answer $\textit{ans} = \max(\textit{ans}, s)$. Continue moving $j$ until $j$ reaches the end of the array.

Finally, return the answer.

The time complexity is $O(n)$, where $n$ is the length of the array. The space complexity is $O(1)$.

<!-- tabs:start -->

Expand Down Expand Up @@ -197,6 +220,29 @@ function maxTotalFruits(fruits: number[][], startPos: number, k: number): number
}
```

#### Rust

```rust
impl Solution {
pub fn max_total_fruits(fruits: Vec<Vec<i32>>, start_pos: i32, k: i32) -> i32 {
let mut ans = 0;
let mut s = 0;
let mut i = 0;
for j in 0..fruits.len() {
let pj = fruits[j][0];
let fj = fruits[j][1];
s += fj;
while i <= j && pj - fruits[i][0] + std::cmp::min((start_pos - fruits[i][0]).abs(), (start_pos - pj).abs()) > k {
s -= fruits[i][1];
i += 1;
}
ans = ans.max(s)
}
ans
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
impl Solution {
pub fn max_total_fruits(fruits: Vec<Vec<i32>>, start_pos: i32, k: i32) -> i32 {
let mut ans = 0;
let mut s = 0;
let mut i = 0;
for j in 0..fruits.len() {
let pj = fruits[j][0];
let fj = fruits[j][1];
s += fj;
while i <= j
&& pj - fruits[i][0]
+ std::cmp::min((start_pos - fruits[i][0]).abs(), (start_pos - pj).abs())
> k
{
s -= fruits[i][1];
i += 1;
}
ans = ans.max(s)
}
ans
}
}