首页 > 其他分享 >力扣刷题——2398. 预算内的最多机器人数目

力扣刷题——2398. 预算内的最多机器人数目

时间:2024-09-13 16:13:18浏览次数:1  
标签:right int subSum long 力扣 vector left 2398 刷题

由题目中求“最多可以连续运行的机器人数目”可知,求的是数组子数组的长度,那么就可以直接使用滑动窗口求解。配合前缀和,可以快速的求得滑动窗口内的运行时间和。那么编写代码如下:

int maximumRobots(vector<int> &chargeTimes, vector<int> &runningCosts, long long budget)
{
    int n = chargeTimes.size();
    vector<long long> subSum;

    subSum.emplace_back(0);
    for (int i = 0; i < n; i++)
    {
        subSum.emplace_back(subSum[i] + runningCosts[i]);
    }

    long long curCost = 0;
    int left = 0;
    int maxCharge;
    int res = 0;
    for (int right = 0; right < n; right++)
    {
        curCost = subSum[right + 1] - subSum[left];
        maxCharge = chargeTimes[left];
        for (int i = left + 1; i <= right; i++)
            maxCharge = max(maxCharge, chargeTimes[i]);
        int temRes = right - left + 1;
        curCost = curCost * temRes + maxCharge;
        if (curCost <= budget)
        {
            res = max(res, temRes);
        }
        else
        {
            left++;
        }
    }
    return res;
}

但是这样会超时,这是因为这段代码,对滑动窗口内的最大充电时间的维护是一个暴力算法,会导致算法整体的时间复杂度到O(n^2)。可以考虑用一个有序的数组来维护滑动窗口内的最大充电时间。比如红黑树,结构中最后一个元素为最大充电时间,在窗口增大缩小时,也能够很快的进行元素的删除和增加,那么有以下实现:

int maximumRobots(vector<int> &chargeTimes, vector<int> &runningCosts, long long budget)
{
    int n = chargeTimes.size();
    vector<long long> subSum;
    map<int, int> mp;
    subSum.emplace_back(0);
    for (int i = 0; i < n; i++)
    {
        subSum.emplace_back(subSum[i] + runningCosts[i]);
    }

    long long curCost = 0;
    int left = 0;
    int res = 0;
    for (int right = 0; right < n; right++)
    {
        curCost = subSum[right + 1] - subSum[left];
        mp[chargeTimes[right]]++;
        int temRes = right - left + 1;
        curCost = curCost * temRes + (--mp.end())->first;
        if (curCost <= budget)
        {
            res = max(res, temRes);
        }
        else
        {
            if (--mp[chargeTimes[left]] == 0)
                mp.erase(chargeTimes[left]);
            left++;
        }
    }
    return res;
}

用红黑树的方法很好理解,但是有点杀鸡用牛刀的意思。。。实现还有优化空间,可以考虑用一个双端队列实现单调队列,以此维护窗口内的最大充电时间,队列的首个元素为最大充电时间。在窗口右拓的时候,可以从后往前舍弃队列中的元素;而在窗口左缩的时候,可以从前往后弹出元素。在队列中存入最大充电时间的下标,将更加容易实现这个代码:

int maximumRobots(vector<int> &chargeTimes, vector<int> &runningCosts, long long budget)
{
    int n = chargeTimes.size();
    vector<long long> subSum;
    deque<int> dq;
    subSum.emplace_back(0);
    for (int i = 0; i < n; i++)
    {
        subSum.emplace_back(subSum[i] + runningCosts[i]);
    }

    long long curCost = 0;
    int left = 0;
    int res = 0;
    for (int right = 0; right < n; right++)
    {
        while (!dq.empty() && chargeTimes[dq.back()] <= chargeTimes[right])
            dq.pop_back();
        dq.push_back(right);

        while (!dq.empty() && (subSum[right + 1] - subSum[left]) * (right - left + 1) + chargeTimes[dq.front()] > budget)
        {
            if (dq.front() == left)
                dq.pop_front();
            left++;
        }

        if (!dq.empty())
            res = max(res, right - left + 1);
    }
    return res;
}

标签:right,int,subSum,long,力扣,vector,left,2398,刷题
From: https://www.cnblogs.com/yuhixyui/p/18412403

相关文章

  • 代码随想录突击版刷题
    704.二分查找https://leetcode.cn/problems/binary-search/description/ 59.螺旋矩阵II https://leetcode.cn/problems/spiral-matrix-ii/description/、参考题解写出54.螺旋矩阵 https://leetcode.cn/problems/spiral-matrix/description/classSolution{public:......
  • 郑轻刷题知识1031-1040
    分类比较少的话用if分类较多的话,用case(是符号的话不要忘了加引号,例如' +')1036:(a为年份,b为月份)  switch(b)  {case1:case3:case5:case7:case8:case10:case12:   printf("31");//1.3.5.7.8.10.12是31天  break;  case2:   ......
  • 【oj刷题】滑动窗口篇:滑动窗口的应用场景和注意事项
    前言:滑动窗口其实基本原理还是双指针,但在双指针中左右指针可能会有回退操作,而滑动窗口的左右指针只会向前走,不会回退,下面就来讲解一下滑动窗口的概念和具体操作(主要是例题讲解)目录一、什么是滑动窗口?二、滑动窗口的原理三、滑动窗口的算法实现四、滑动窗口的例题讲解......
  • 刷题活动(旋转和翻转)
        前两天打了CCPC网络赛(让打老实了),现在认识到了刷题的重要性,于是我开创了这么个栏目,我们一起刷一下题。    还是在ACwing网站上刷题 旋转和翻转         首先,申一下题目,输入一个数字n,来表示矩阵的行和列,之后输入两个矩阵,判断一下两个矩阵相......
  • LeetCode刷题
    2.11378.使用唯一标识码替换员工ID2.1.1说明Employees表:±--------------±--------+|ColumnName|Type|±--------------±--------+|id|int||name|varchar|±--------------±--------+在SQL中,id是这张表的主键。这张表的每一行分别代表了某......
  • leetcode刷题
    3.1力扣之1421-净现值查询3.1.1说明表:NPV±--------------±--------+|ColumnName|Type|±--------------±--------+|id|int||year|int||npv|int|±--------------±--------+(id,year)是该表主键(具有唯一值的列的组合).该表有每一笔存......
  • 题解 力扣 LeetCode 105 从前序与中序遍历序列构造二叉树 C/C++
    题目传送门:105.从前序与中序遍历序列构造二叉树-力扣(LeetCode)https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/每次在中序遍历序列片段中找到前序遍历序列队首,这是该层的根节点该位置左侧是左子树,右侧是右子树再......
  • 【力扣16】最接近的三数之和
    16.最接近的三数之和-力扣(LeetCode)接近target:大于或小于两种情况。但是实际操作中只需考虑大于的情况,找到之后结果的前一个数也有可能是结果,进行比较(更新结果res)。第二种情况的实现依靠右指针的移动思路类似15对于每个j,找到一个最小的k,使得满足条件(j变大,k一定减小即k--)......
  • 力扣238 移动零 Java版本 时间复杂度为O(0)
    文章目录题目描述代码题目描述给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请注意,必须在不复制数组的情况下原地对数组进行操作。示例1:输入:nums=[0,1,0,3,12]输出:[1,3,12,0,0]示例2:输入:nums=[0]输出......
  • 【每日刷题】Day119
    【每日刷题】Day119......