【算法】【贪心】621. Task Scheduler

Given a characters array tasks, representing the tasks a CPU needs to do, where each letter represents a different task. Tasks could be done in any order. Each task is done in one unit of time. For each unit of time, the CPU could complete either one task or just be idle.

However, there is a non-negative integer n that represents the cooldown period between two same tasks (the same letter in the array), that is that there must be at least n units of time between any two same tasks.

Return the least number of units of times that the CPU will take to finish all the given tasks.

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/task-scheduler
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


分析

太逆天了这道题,真滴难想。
这个模型,真的牛
整体上模拟法,比较好想,但是估计不太好实现,这里也懒得写了。

直接看重要的贪心法
在这里插入图片描述
整体上,我们选出数量最多的task,作为A,他必然是每轮中需要第一次执行的。考虑每次执行A后的n个slot,这样我们形成了一个长为n+1,高为numA-1的矩形,他的第一列为A,我们要把剩下的所有任务填入这个矩形当中
考虑B,最多和A数量一样,因此不会超过一列,
考虑一个任务数量较少的情况。这里最为关键,实际是按照列优先,优先选择最左侧的列,优先选择最下方的行 如图中EF,这个反向放置方法十分精妙,他的结果是使得同种任务的间隔最少为n,绝绝子。
这样的话如果还有槽位剩余,就说明就应该按照这样调度,空slot即idle时间
否则就说明空槽位不需要,但顺序仍然按照这样调度。

实现1

class Solution {
public:
    int leastInterval(vector<char>& tasks, int n) {
        vector<int> vec(26);
        for(char c: tasks) {
            vec[c - 'A']++;
        }
        sort(vec.begin(), vec.end());
        int maxVal = vec[25] - 1;
        int idleSlots = maxVal * n;
        for(int i = 24; i >= 0 && vec[i] > 0; --i) {
            idleSlots -= min(vec[i], maxVal);
        }
        return idleSlots > 0 ? idleSlots + tasks.size() : tasks.size();
    }
};

这种是比较好理解的实现

实现2

class Solution {
public:
    int leastInterval(vector<char>& tasks, int n) {
        unordered_map<char, int> freq;
        for (char ch: tasks) {
            ++freq[ch];
        }

        // 最多的执行次数
        int maxExec = max_element(freq.begin(), freq.end(), [](const auto& u, const auto& v) {
            return u.second < v.second;
        })->second;
        // 具有最多执行次数的任务数量
        int maxCount = accumulate(freq.begin(), freq.end(), 0, [=](int acc, const auto& u) {
            return acc + (u.second == maxExec);
        });

        return max((maxExec - 1) * (n + 1) + maxCount, static_cast<int>(tasks.size()));
    }
};

比较抽象,但是大体意思和上面差不多,这里面不同库函数中lambda的使用值得学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值