Skip to content

Commit 182fba7

Browse files
authored
feat: add solutions to lc problem: No.2106 (doocs#4614)
No.2106.Maximum Fruits Harvested After at Most K Steps
1 parent 7bb3abb commit 182fba7

File tree

3 files changed

+102
-11
lines changed

3 files changed

+102
-11
lines changed

solution/2100-2199/2106.Maximum Fruits Harvested After at Most K Steps/README.md

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,24 +83,24 @@ tags:
8383

8484
### 方法一:双指针
8585

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

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

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

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

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

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

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

103-
每次我们将 $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$ 到达数组末尾。
103+
每次我们将 $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$ 到达数组末尾。
104104

105105
最后返回答案即可。
106106

@@ -219,6 +219,29 @@ function maxTotalFruits(fruits: number[][], startPos: number, k: number): number
219219
}
220220
```
221221

222+
#### Rust
223+
224+
```rust
225+
impl Solution {
226+
pub fn max_total_fruits(fruits: Vec<Vec<i32>>, start_pos: i32, k: i32) -> i32 {
227+
let mut ans = 0;
228+
let mut s = 0;
229+
let mut i = 0;
230+
for j in 0..fruits.len() {
231+
let pj = fruits[j][0];
232+
let fj = fruits[j][1];
233+
s += fj;
234+
while i <= j && pj - fruits[i][0] + std::cmp::min((start_pos - fruits[i][0]).abs(), (start_pos - pj).abs()) > k {
235+
s -= fruits[i][1];
236+
i += 1;
237+
}
238+
ans = ans.max(s)
239+
}
240+
ans
241+
}
242+
}
243+
```
244+
222245
<!-- tabs:end -->
223246

224247
<!-- solution:end -->

solution/2100-2199/2106.Maximum Fruits Harvested After at Most K Steps/README_EN.md

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ tags:
3333
<pre>
3434
<strong>Input:</strong> fruits = [[2,8],[6,3],[8,6]], startPos = 5, k = 4
3535
<strong>Output:</strong> 9
36-
<strong>Explanation:</strong>
36+
<strong>Explanation:</strong>
3737
The optimal way is to:
3838
- Move right to position 6 and harvest 3 fruits
3939
- Move right to position 8 and harvest 6 fruits
@@ -45,7 +45,7 @@ You moved 3 steps and harvested 3 + 6 = 9 fruits in total.
4545
<pre>
4646
<strong>Input:</strong> fruits = [[0,9],[4,1],[5,7],[6,2],[7,4],[10,9]], startPos = 5, k = 4
4747
<strong>Output:</strong> 14
48-
<strong>Explanation:</strong>
48+
<strong>Explanation:</strong>
4949
You can move at most k = 4 steps, so you cannot reach position 0 nor 10.
5050
The optimal way is to:
5151
- Harvest the 7 fruits at the starting position 5
@@ -82,7 +82,30 @@ You can move at most k = 2 steps and cannot reach any position with fruits.
8282

8383
<!-- solution:start -->
8484

85-
### Solution 1
85+
### Solution 1: Two Pointers
86+
87+
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:
88+
89+
1. If $\textit{startPos} \leq l$, then we move right from $\textit{startPos}$ to $r$. The minimum number of steps is $r - \textit{startPos}$;
90+
2. If $\textit{startPos} \geq r$, then we move left from $\textit{startPos}$ to $l$. The minimum number of steps is $\textit{startPos} - l$;
91+
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)$.
92+
93+
All three cases can be unified by the formula $r - l + \min(\lvert \textit{startPos} - l \rvert, \lvert r - \textit{startPos} \rvert)$.
94+
95+
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:
96+
97+
1. If $\textit{startPos} \leq l$, as $l$ increases, the minimum number of steps remains unchanged.
98+
2. If $\textit{startPos} > l$, as $l$ increases, the minimum number of steps decreases.
99+
100+
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.
101+
102+
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$.
103+
104+
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.
105+
106+
Finally, return the answer.
107+
108+
The time complexity is $O(n)$, where $n$ is the length of the array. The space complexity is $O(1)$.
86109

87110
<!-- tabs:start -->
88111

@@ -197,6 +220,29 @@ function maxTotalFruits(fruits: number[][], startPos: number, k: number): number
197220
}
198221
```
199222

223+
#### Rust
224+
225+
```rust
226+
impl Solution {
227+
pub fn max_total_fruits(fruits: Vec<Vec<i32>>, start_pos: i32, k: i32) -> i32 {
228+
let mut ans = 0;
229+
let mut s = 0;
230+
let mut i = 0;
231+
for j in 0..fruits.len() {
232+
let pj = fruits[j][0];
233+
let fj = fruits[j][1];
234+
s += fj;
235+
while i <= j && pj - fruits[i][0] + std::cmp::min((start_pos - fruits[i][0]).abs(), (start_pos - pj).abs()) > k {
236+
s -= fruits[i][1];
237+
i += 1;
238+
}
239+
ans = ans.max(s)
240+
}
241+
ans
242+
}
243+
}
244+
```
245+
200246
<!-- tabs:end -->
201247

202248
<!-- solution:end -->
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
impl Solution {
2+
pub fn max_total_fruits(fruits: Vec<Vec<i32>>, start_pos: i32, k: i32) -> i32 {
3+
let mut ans = 0;
4+
let mut s = 0;
5+
let mut i = 0;
6+
for j in 0..fruits.len() {
7+
let pj = fruits[j][0];
8+
let fj = fruits[j][1];
9+
s += fj;
10+
while i <= j
11+
&& pj - fruits[i][0]
12+
+ std::cmp::min((start_pos - fruits[i][0]).abs(), (start_pos - pj).abs())
13+
> k
14+
{
15+
s -= fruits[i][1];
16+
i += 1;
17+
}
18+
ans = ans.max(s)
19+
}
20+
ans
21+
}
22+
}

0 commit comments

Comments
 (0)