原题链接
一. 题目描述
你有 n 个机器人,给你两个下标从 0 开始的整数数组 chargeTimes 和 runningCosts ,两者长度都为 n 。第 i 个机器人充电时间为 chargeTimes[i] 单位时间,花费 runningCosts[i] 单位时间运行。再给你一个整数 budget 。
运行 k 个机器人 总开销 是 max(chargeTimes) + k * sum(runningCosts) ,其中 max(chargeTimes) 是这 k 个机器人中最大充电时间,sum(runningCosts) 是这 k 个机器人的运行时间之和。
请你返回在 不超过 budget 的前提下,你 最多 可以 连续 运行的机器人数目为多少。
示例 1:
输入:chargeTimes = [3,6,1,3,4], runningCosts = [2,1,3,4,5], budget = 25
输出:3
解释:
可以在 budget 以内运行所有单个机器人或者连续运行 2 个机器人。
选择前 3 个机器人,可以得到答案最大值 3 。总开销是 max(3,6,1) + 3 * sum(2,1,3) = 6 + 3 * 6 = 24 ,小于 25 。
可以看出无法在 budget 以内连续运行超过 3 个机器人,所以我们返回 3 。
示例 2:
输入:chargeTimes = [11,12,19], runningCosts = [10,8,7], budget = 19
输出:0
解释:即使运行任何一个单个机器人,还是会超出 budget,所以我们返回 0 。
提示:
chargeTimes.length == runningCosts.length == n
1 <= n <= 5 * 104
1 <= chargeTimes[i], runningCosts[i] <= 105
1 <= budget <= 1015
二. 解题思路
本题在LeetCode中标签为困难,但是思考一下并不难,题目有个坑就是这个序列必须是连续的,这里需要注意一下,对于选择连续的区间问题,我们自然而然可以想到利用滑动窗口和双指针解决问题。
在这里还需要注意一下,因为是在最终选择区间计算的时候是max(chargeTimes),所以我们选择使用优先队列存储下标right。
不断遍历数组,将较大的chargeTimes[right]添加到队列中,并且将小于chargeTimes[right]的下标出队(没有存储的必要),然后使用sum变量累加runningCosts[right]的值。
然后我们再来判断所选择的区间和budget的大小,如果计算结果大于budget,我们将left指针右移,并且sum减去移动的left的runningCosts[left],直到首个满足budget的left指针时退出while循环。
最后我们使用ans来取最大区间即可。
话不多说!!!上代码!!
三. 代码
cpp
class Solution {
public:
#define ll long long
int maximumRobots(vector<int>& chargeTimes, vector<int>& runningCosts, long long budget) {
int ans = 0, left = 0;
ll sum = 0;
deque<int> q;
for(int right = 0; right < chargeTimes.size(); right++){
// 进队列,将最大的元素保留在队头
while(!q.empty() && chargeTimes[right] >= chargeTimes[q.back()]){
q.pop_back();
}
q.push_back(right);
// 计算前right个机器人的运行时间
sum += runningCosts[right];
// 当发现计算结果大于budget的时候移动左指针
while(!q.empty() && chargeTimes[q.front()] + (right - left + 1) * sum > budget){
if(q.front() == left){
q.pop_front();
}
sum -= runningCosts[left++];
}
// 计算最大能运行的机器数目
ans = max(ans, right - left + 1);
}
return ans;
}
};
四. 总结
时间复杂度:O(n);
空间复杂度:O(n)