leetcode 大顶堆使用

题目

给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。

然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。

你需要计算完成所有任务所需要的 最短时间 。

例如:
输入:tasks = [“A”,“A”,“A”,“B”,“B”,“B”], n = 2
输出:8
解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B
在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。
https://leetcode-cn.com/problems/task-scheduler/

基本思路

(1)构建一个 优先队列,大顶堆,用于存剩余任务的次数。例如 [ 8,5,5,4,3],此处不区分任务种类,因为即使两个任务数量一样,相对次序不影响结果。可以把希望的次序作为要使用的次序。
(2)以任务间隔 作为一个周期,按任务次数的多少依次取出数量最大的任务,
如果间隔够大,所有任务取一遍也不能填满,那么就用空白代替,取出任务的数量都减一,数量不为0的,再添加到 队列中。
如果间隔较小,任务取一部分就填满间隔,那么取出任务的数量都减一,数量不为0的,再添加到 队列中。

代码

class Solution {
public:
    int leastInterval(vector<char>& tasks, int n) {
        int ans = 0;
        
        priority_queue<int> p_que;  //建立一个自动排序的大顶堆
        unordered_map<char,int> num_map; 
        for(const auto &r:tasks){  //统计每个任务的个数
            ++num_map[r];
        }
        for(const auto &r:num_map){ //压入大顶堆
            //cout<<r.second<<endl;
            p_que.push(r.second);
        }

        while(!p_que.empty()){  //任务未完成的时候,继续执行任务
            vector<int> temp;   //用于存下,已经执行,但是还剩余执行次数的任务
            for(int i=0;i<=n;++i){  //以间隔次数作为一个周期
                ++ans;         //记下花费的单位时间
                if(!p_que.empty()){  //在一个间隔内,队列中还有其他任务没有被做过
                    if(p_que.top() - 1 != 0){  //做队列中剩余次数最多的任务
                        temp.push_back(p_que.top() - 1); //如果还有剩余,暂时先存下
                    }
                    p_que.pop();  //弹出做过的任务
                }
                if(p_que.empty() && temp.size()==0)
                    break;//如果队列 和 暂存temp 都为空,说明任务已经完成
            }
            for(const auto &r:temp){ //一个周期之后,将temp 中的任务再添加回来。
                p_que.push(r);
            }
        }
        return ans;
    }
};

大顶堆

https://blog.csdn.net/xiaoquantouer/article/details/52015928?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control 参考
https://blog.csdn.net/stone_fall/article/details/89010656?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control 参考

学习例子:

class Solution {
public:
    int leastInterval(vector<char>& tasks, int n) {
        auto cmp = [&](vector<int> &letter1, vector<int> &letter2){
            return letter1[1] < letter2[1];
        };
        priority_queue<vector<int>, vector<vector<int>>,decltype(cmp)> p_que(cmp);
        unordered_map<int,int> num_map;

        for(const auto &r:tasks){
            ++num_map[r - 'A'];
        }
        for(const auto &r:num_map){
            vector<int> temp;
            temp.push_back(r.first);
            temp.push_back(r.second);
            p_que.push(temp);
        }

        while( !p_que.empty()){
            cout<<p_que.top()[1]<<endl;
            p_que.pop();
        }
        return 0;
    }
};

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值