当前位置: 首页 > article >正文

【数据结构-堆】【二分】力扣3296. 移山所需的最少秒数

给你一个整数 mountainHeight 表示山的高度。

同时给你一个整数数组 workerTimes,表示工人们的工作时间(单位:秒)。

工人们需要 同时 进行工作以 降低 山的高度。对于工人 i :

山的高度降低 x,需要花费 workerTimes[i] + workerTimes[i] * 2 + … + workerTimes[i] * x 秒。例如:
山的高度降低 1,需要 workerTimes[i] 秒。
山的高度降低 2,需要 workerTimes[i] + workerTimes[i] * 2 秒,依此类推。
返回一个整数,表示工人们使山的高度降低到 0 所需的 最少 秒数。

示例 1:
输入: mountainHeight = 4, workerTimes = [2,1,1]

输出: 3

解释:

将山的高度降低到 0 的一种方式是:

工人 0 将高度降低 1,花费 workerTimes[0] = 2 秒。
工人 1 将高度降低 2,花费 workerTimes[1] + workerTimes[1] * 2 = 3 秒。
工人 2 将高度降低 1,花费 workerTimes[2] = 1 秒。
因为工人同时工作,所需的最少时间为 max(2, 3, 1) = 3 秒。

示例 2:
输入: mountainHeight = 10, workerTimes = [3,2,2,4]

输出: 12

解释:

工人 0 将高度降低 2,花费 workerTimes[0] + workerTimes[0] * 2 = 9 秒。
工人 1 将高度降低 3,花费 workerTimes[1] + workerTimes[1] * 2 + workerTimes[1] * 3 = 12 秒。
工人 2 将高度降低 3,花费 workerTimes[2] + workerTimes[2] * 2 + workerTimes[2] * 3 = 12 秒。
工人 3 将高度降低 2,花费 workerTimes[3] + workerTimes[3] * 2 = 12 秒。
所需的最少时间为 max(9, 12, 12, 12) = 12 秒。

示例 3:
输入: mountainHeight = 5, workerTimes = [1]

输出: 15

解释:

这个示例中只有一个工人,所以答案是 workerTimes[0] + workerTimes[0] * 2 + workerTimes[0] * 3 + workerTimes[0] * 4 + workerTimes[0] * 5 = 15 秒。

最小堆

class Solution {
public:
    long long minNumberOfSeconds(int mountainHeight, vector<int>& workerTimes) {
        priority_queue<tuple<long long, int, int>, vector<tuple<long long, int, int>>, greater<tuple<long long, int, int>>> q;

        for(int i = 0; i < workerTimes.size(); i++){
            q.push({(long long)workerTimes[i], i, 1});
        }

        long long ans = 0;
        for(int i = 0; i < mountainHeight; i++){
            auto [Time, idx, cnt] = q.top();
            q.pop();
            ans = max(ans, Time);
            int nextCnt = cnt + 1;
            long long nextTime = Time + (long long)workerTimes[idx] * nextCnt;
            q.push({nextTime, idx, nextCnt});
        }

        return ans;
    }
};

时间复杂度:O(mountainHeightlogn),其中 n 是 workerTimes 的长度。
空间复杂度:O(n)。

这道题我们要注意的是工人是同时工作的,我们要求他最少时间,那么也就是说我们要让干最久的工人的时间尽可能少。首先我们由题目可以知道,假如我们把移山的任务分成每个单位,那么我们可以由工人的workerTimes和他操作的次数来判断他完成这个任务所需要的时间。我们定义一个三元组tuple<long long, int, int>,分别对应工作累积时间、工人序号、操作的对应次数。我们建立一个最小堆q来储存工人下一次移除单位后的累积时间是多少,然后我们每次选择q的队头也就是完成下一单位后累计工作时间最少的工人。并且我们定义一个变量ans来记录最大的累计工作时间,最后ans中储存的就是完成移山所需得到最少秒数。

二分

class Solution {
public:
    long long minNumberOfSeconds(int mountainHeight, vector<int>& workerTimes) {
        //每个工人至多花费 m 秒,总共降低的高度是多少?能否大于等于 mountainHeight?
        auto check = [&](long long m){
            int left_h = mountainHeight;
            for(int t : workerTimes){
                left_h -= ((int)sqrt(1 + 8 * m / t) - 1) / 2;
                if(left_h <= 0){
                    return true;
                }
            }
            return false;
        };

        //假设每个工人都是最慢的maxT
        int max_t = ranges::max(workerTimes);
        int h = (mountainHeight - 1) / workerTimes.size() + 1; //用于计算二分上界
        long long left = 0, right = (long long)max_t * h * (h+1)/2;
        while(left + 1 < right){
            long long mid = (left + right) / 2;
            (check(mid) ? right : left) = mid;
        }
        return right;
    }
};

在这里插入图片描述
别人写的题解


http://www.kler.cn/a/472888.html

相关文章:

  • 代码随想录算法训练营day23
  • TensorRT-LLM中的MoE并行推理
  • 【Go学习】-02-1-标准库:fmt、os、time
  • GaussDB SQL调优之改写SQL消除子查询
  • oracle闪回恢复数据:(闪回查询,闪回表,闪回库,回收站恢复)
  • 【AJAX详解】
  • 牛客网刷题 ——C语言初阶(5操作符)——BC90 矩阵计算
  • 解决word桌面图标空白
  • UTTracker背景矫正模块详解:解决无人机追踪中的摄像头运动问题
  • Ruby语言的正则表达式
  • WebSocket 设计思路
  • 怎样用云手机进行海外社媒矩阵引流?
  • 【Linux】lnav - 适用于Linux和Unix的出色终端日志文件查看器
  • windows从0开始配置llamafactory微调chatglm3-6b
  • 使用vue-pdf预览pdf和解决pdf电子签章显示问题
  • 【中标喜讯分享】泰迪智能科技实力中标长春医学高等专科学校健康大数据管理与服务专业实训软件采购项目
  • 计算机网络——期末复习(7)期末试卷样例3
  • CSS语言的软件工程
  • STM32-DMA数据转运
  • react-quill 富文本组件编写和应用
  • 【合作原创】使用Termux搭建可以使用的生产力环境(九)
  • el-table设置单元格行高间距
  • 从 0 开始上手 Solana 智能合约
  • 网站运营数据pv、uv、ip
  • 200多个高分辨率婚礼旅拍不同环境天空替换素材 Visualsofjulius - Sky Bundle II
  • 基于FPGA的出租车里程时间计费器