LeetCode 每日一题 预算内的最多机器人数目

预算内的最多机器人数目

你有 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

解题思路

  • 首先需要讲清楚:题目中提到的连续运行的机器人,是指连续的机器人,也就是子数组

首先我的思路是用双指针然后贪心,踢掉大的那一个,但是很显然局部最优解并不能得到正确答案

接着发现:双指针包含的数据越多,花费的时间也就越多,我们可以使用滑动窗口进行枚举,找到最大的机器人数为答案

接着需要注意的是我们要得到滑动窗口包含的chargeTimes的最大值以及runningCoasts的和

runningCoasts的和很好获取,在我们枚举右指针的时候加,在移动左指针的时候减

获取chargeTimes的最大值则使用一个单调队列 arr 进行存储,队列是递减的,在将要插入新数据的时候不断检查队尾的数据是否小于新数据,如果小于新数据,就将其弹出(注意尾要大于头),这样就维护了一个递减队列,队列的头就是滑动窗口中数据的最大值

接下来看看枚举的思路

首先用for循环枚举右指针,从0到最后

然后用while循环检查维护队列

然后向队列插入新数据

由于数据越多,时间就越多,所以当时间超过budget时,左指针就需要++了,所以用一个while循环检查时间是否超过budget,如果超过了,判断左指针的数据是否是此时数据的最大值,也就是是否与队列的头相等,如果相等,队列的头就需要++,将其弹出。然后记录数据的和的sum减去左指针指向的数。最后左指针++(注意左指针小于等于右指针)

最后就是不断判断时间小于等于budget的数据的长度,记录其中的最大值,返回即可

代码如下↓

int maximumRobots(int* chargeTimes, int chargeTimesSize, int* runningCosts, int runningCostsSize, long long budget) {
    int l=0,r=0;
    int res = 0;
    int* arr = (int*)malloc(sizeof(int)*chargeTimesSize);
    int h=0,t=0;
    long long sum=0;
    for(r=0;r<chargeTimesSize;r++)
    {
        sum+=runningCosts[r];
        while(h<t && chargeTimes[r]>arr[t-1])
        {
            t--;
        }//维护队列的单调递减性
        arr[t] = chargeTimes[r];
        t++;
        while(l<=r && arr[h] + (r-l+1)*sum > budget)
        {
            if(chargeTimes[l] == arr[h])
            {
                h++;
            }
            sum-=runningCosts[l];
            l++;
        }
        if(r-l+1>res)
        {
            res = r-l+1;
        }
    }
    free(arr);
    return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值