记力扣2106.摘水果 练习理解
在一个无限的 x 坐标轴上,有许多水果分布在其中某些位置。给你一个二维整数数组
fruits
,其中fruits[i] = [positioni, amounti]
表示共有amounti
个水果放置在positioni
上。fruits
已经按positioni
升序排列 ,每个positioni
互不相同 。另给你两个整数
startPos
和k
。最初,你位于startPos
。从任何位置,你可以选择 向左或者向右 走。在 x 轴上每移动 一个单位 ,就记作 一步 。你总共可以走 最多k
步。你每达到一个位置,都会摘掉全部的水果,水果也将从该位置消失(不会再生)。返回你可以摘到水果的 最大总数 。
思路:
首先使用二分查找 (
bisect_left
) 找到第一个位置不小于startPos - k
的水果,这是我们可能需要考虑的左边界起点。然后遍历从这个左边界开始的所有水果:
- 如果水果位置超出
startPos + k
,直接跳出循环,因为这些水果不可能被收集到- 累加当前水果的数量到总和
s
中- 使用一个 while 循环来调整左边界,确保当前窗口内的水果都能在
k
步内收集到- 更新最大水果数量
ans
最后返回最大水果数量
ans
这个算法的核心是维护一个滑动窗口,窗口内的水果都能在
k
步内从startPos
到达。其中判断条件i*2-startPos-fruits[left][0]>k and i+startPos-fruits[left][0]*2>k
是为了确保无论是先向左再向右,还是先向右再向左,都能在k
步内覆盖整个窗口范围。
class Solution:def maxTotalFruits(self,fruits:List[int],startPos:int,k:int)->int:left=bisect_left(fruits,[startPos-k])ans=s=0for i ,char in fruits[left:]:if i>startPos+k:breaks+=charwhile i*2-startPos-fruits[left][0]>k and i+startPos-fruits[left][0]*2>k:s-=fruits[left][1]left +=1ans=max(ans,s)return ans
难点:
1.想到利用二分查找去找到第一个出现刚好不低于startPos-k的索引作为左端。
2. 通过判断(如果是先右后左:他的步数为i-startPos+i-fruits[left][0];;如果是先左后右:startPos-fruits[left][0]+i-fruits[left][0])步长是否超过k为依据,如果超过了移动左边界更新最大值来计算