单调队列-下
题目1
题目链接:862. 和至少为 K 的最短子数组
解题思路
- 前缀和加单调双端队列,维护一个单增的单调序列,存放前缀和数组的下标,对于数组中的每个位置i,我们要找到以它为结尾的和至少为k的最短子数组,要在前面找到一个最右边界,使得
sum[i] - sum[x] >= k,i-x即为以i结尾的最短长度,只需比较数组每个元素作为最后一个元素的最小值即可找到答案 - 删除队首:当
sum[i] - sum[deque[h]] >= k时,说明找到了一个满足条件的子数组,记录长度并弹出队首(因为后续更大的i不会得到更短的结果) - 删除队尾:如果当前
sum[i] <= sum[deque[t-1]],那么deque[t-1]这个位置永远不会再被用作左端点,因为i更靠右且前缀和更小,是更好的选择
代码
1 | class Solution { |
题目2
题目链接:1499. 满足不等式的最大值
解题思路
yi + yj + |xi - xj|等价于(xj+yj)+(yi-xi),即在规定范围内((xj-xi)<=k)找(yi-xi)的最大值- 我们维护一个****双端队列,队列中存储的是候选点
(xi, yi),并按照(yi - xi)从大到小排列(即队首是当前窗口内(yi - xi)最大的点) - 移除过远的点,若队首满足
xj-xi>k,说明它不再合法窗口内,从队首弹出 - 更新答案,如果队列非空,队首就是答案
- 维护队列单调性,把当前点
(xj,yj)加到队列前,从队尾删除所有(yi-xi)<=(yj-xj)的点- **当前点更靠右(x 更大),未来能存活更久(不容易被 **
xj - xi > k踢出) - **且 **
(yj - xj)更大,是更优的候选
- **当前点更靠右(x 更大),未来能存活更久(不容易被 **
代码
1 | class Solution { |
题目3
题目链接:2071. 你可以安排的最多任务数目
解题思路(二分+贪心+双端队列)
- 解决任务的范围是
0,Math.min(tsize,wsize),右侧为任务数和工人数的最小值,如果能完成一半的任务,记录答案,去右侧二分,否则去左侧二分,现在的难点是能否完成这么多的任务 - 我们将任务数组和工人数组排好序
- 我们可以在 tasks 中选择 k 个值最小的任务;
- 我们可以在 workers 中选择 k 个值最大的工人。
- 遍历工人数组,如果工人不吃药就能解决任务,把能解决的任务加入队列,并弹出队首(该任务被解决)
- 如果工人不吃药解决不了任务,吃药,并将吃药后能解决的任务加到队列,并弹出队尾(发挥药的最大作用),如果吃药仍不能解决任务,直接返回
false,用cnt变量记录所用药数,如果所需药数小于等于所给药数,返回true
代码
1 | class Solution { |
本文是原创文章,采用CC BY-NC-SA 4.0协议,完整转载请注明来自Heaven
