2106: Maximum-Fruits-Harvested-After-at-Most-K-Steps
Hard
table of contents
The intuition behind this algorithm is not that hard; just coding it up is a pain in the backside.
For simplicity, if we left-shift all the indices by
startPos
, we can assume that the question is basically
zero-indexed (which will make explaining simpler).
Now, the main intuition is that, if we want to optimally traverse the x-axis, we should make a maximum of only one direction change. That leaves us with only a limited number of windows that we have to check; we can use a sliding window to check this.
For example, given a value of k = 8
, we have the
options:
8 <= 0 // traverse 8 spaces to the left
6 <= 0 => 1 // traverse 1 spaces to the right, then 7 spaces to the left
4 <= 0 => 2 // traverse 2 spaces to the right, then 6 spaces to the left
2 <= 0 => 3 // traverse 3 spaces to the right, then 5 spaces to the left
// change the direction up!
3 <= 0 => 2 // traverse 3 spaces to the left, then 5 spaces to the right
2 <= 0 => 4 // traverse 2 spaces to the left, then 6 spaces to the right
1 <= 0 => 6 // traverse 1 spaces to the left, then 7 spaces to the right 0 => 8 // traverse 8 spaces to the right
In essence, we start up with a window where we traverse
k
spaces to the left. Then, we can just shift our
left-index by 2
and our
right-index by 1
until the
right-index is greater than our
left-index.
Afterwards, we reverse our left-index and
right-index differences, before shifting our
left-index by 1
and our
right-index by 2
until the
left-index is zero-indexed.
Finally, we can just keep track of our max ans
in every
sliding window before returning it.
code
class Solution {
public:
int maxTotalFruits(vector<vector<int>>& fruits, int startPos, int k) {
int currSum = 0;
int leftIndex = 0;
int leftIndexValue = startPos-k;
while(leftIndex < fruits.size() && fruits[leftIndex][0] < leftIndexValue) {
++leftIndex;
}
int rightIndex = leftIndex;
int rightIndexValue = startPos;
while (rightIndex < fruits.size() && fruits[rightIndex][0] <= startPos) {
+= fruits[rightIndex][1];
currSum ++rightIndex;
}
int ans = currSum;
while (rightIndex < fruits.size() && startPos - leftIndexValue > rightIndexValue - startPos) {
+= 2;
leftIndexValue += 1;
rightIndexValue while (fruits[leftIndex][0] < leftIndexValue) {
-= fruits[leftIndex][1];
currSum ++leftIndex;
}
if (fruits[rightIndex][0] <= rightIndexValue) {
+= fruits[rightIndex][1];
currSum ++rightIndex;
}
= max(ans, currSum);
ans }
int incrementValue = 2 * startPos - leftIndexValue - rightIndexValue;
+= incrementValue;
rightIndexValue while(rightIndex > 0 && fruits[rightIndex-1][0] > rightIndexValue) {
-= fruits[rightIndex-1][1];
currSum --rightIndex;
}
+= incrementValue;
leftIndexValue while(leftIndex > 0 && fruits[leftIndex-1][0] >= leftIndexValue) {
+= fruits[leftIndex-1][1];
currSum --leftIndex;
}
= max(ans, currSum);
ans while (rightIndex < fruits.size() && leftIndexValue < startPos) {
+= 1;
leftIndexValue += 2;
rightIndexValue if (fruits[leftIndex][0] < leftIndexValue) {
-= fruits[leftIndex][1];
currSum ++leftIndex;
}
while (rightIndex < fruits.size() && fruits[rightIndex][0] <= rightIndexValue) {
+= fruits[rightIndex][1];
currSum ++rightIndex;
}
= max(ans, currSum);
ans }
return ans;
}
};