滑动窗口+单调队列

题目:

2398. 预算内的最多机器人数目

答案:

# from typing import List
# from collections import deque
class Solution:
    def maximumRobots(self, chargeTimes: List[int], runningCosts: List[int], budget: int) -> int:
        res, n, runningCostSum = 0, len(chargeTimes), 0
        q, i = deque(), 0
        for j in range(n):
            runningCostSum += runningCosts[j]
            # 维护q,保证它递减
            while q and chargeTimes[q[-1]] <= chargeTimes[j]:
                q.pop()
            q.append(j)
            # i==j还进入循环,说明这里一个都不行,i会变成i+1退出循环,cost都会被清空
            while i <= j and (j - i + 1) * runningCostSum + chargeTimes[q[0]] > budget:
                # 如果i是目前最大的,只需移除它即可,有j作为保障
                if q and q[0] == i:
                    q.popleft()
                runningCostSum -= runningCosts[i]
                i += 1
            res = max(res, j - i + 1)
        return res

''' 滑动窗口、双指针
关键是用q来维持chargeTime最大值
每次j向后移,都会将j加入,同时清除j前面比j小的,这就保证了队列里的charge是递减的,
当某次i需要向后移,且i就是最大charge时,直接删掉这一个q就行,后面一定有第二大或者最后加的j
'''

总结:

  1. 滑动窗口就是这样一个数组,j逐个往后增,每轮对i按要求进行左右移动,不断重复此过程
  2. 滑动窗口里的最大最小值,关键是用单调队列,j又一定会添加进去,保证无论i怎么变,都能直接找到下一个最值

补充:滑动窗口模板

在LeetCode看到的一个评论

//外层循环扩展右边界,内层循环扩展左边界
for (int l = 0, r = 0 ; r < n ; r++) {
	//当前考虑的元素
	while (l <= r && check()) {//区间[left,right]不符合题意
        //扩展左边界
    }
    //区间[left,right]符合题意,统计相关信息
}
posted @ 2024-09-13 20:08  faf4r  阅读(2)  评论(0编辑  收藏  举报