加载中...
621-任务调度器(Task Scheduler)
发表于:2021-12-03 | 分类: 中等
字数统计: 773 | 阅读时长: 3分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/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.

 

Example 1:

Input: tasks = ["A","A","A","B","B","B"], n = 2
Output: 8
Explanation: 
A -> B -> idle -> A -> B -> idle -> A -> B
There is at least 2 units of time between any two same tasks.

Example 2:

Input: tasks = ["A","A","A","B","B","B"], n = 0
Output: 6
Explanation: On this case any permutation of size 6 would work since n = 0.
["A","A","A","B","B","B"]
["A","B","A","B","A","B"]
["B","B","B","A","A","A"]
...
And so on.

Example 3:

Input: tasks = ["A","A","A","A","A","A","B","C","D","E","F","G"], n = 2
Output: 16
Explanation: 
One possible solution is
A -> B -> C -> A -> D -> E -> A -> F -> G -> A -> idle -> idle -> A -> idle -> idle -> A

 

Constraints:

  • 1 <= task.length <= 104
  • tasks[i] is upper-case English letter.
  • The integer n is in the range [0, 100].

中文题目

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

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

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

 

示例 1:

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

示例 2:

输入:tasks = ["A","A","A","B","B","B"], n = 0
输出:6
解释:在这种情况下,任何大小为 6 的排列都可以满足要求,因为 n = 0
["A","A","A","B","B","B"]
["A","B","A","B","A","B"]
["B","B","B","A","A","A"]
...
诸如此类

示例 3:

输入:tasks = ["A","A","A","A","A","A","B","C","D","E","F","G"], n = 2
输出:16
解释:一种可能的解决方案是:
     A -> B -> C -> A -> D -> E -> A -> F -> G -> A -> (待命) -> (待命) -> A -> (待命) -> (待命) -> A

 

提示:

  • 1 <= task.length <= 104
  • tasks[i] 是大写英文字母
  • n 的取值范围为 [0, 100]

通过代码

高赞题解

参考「桶思想」,详细说明各种情况

建立大小为 n+1 的桶子,个数为任务数量最多的那个任务,比如下图,等待时间 n=2,A 任务个数 6 个,我们建立 6 桶子,每个容量为 3:

我们可以把一个桶子看作一轮任务

6XC91X9Y3AV)2)9{Y]2@QWS.png

  1. 先从最简单的情况看起,现在就算没有其他任务,我们完成任务 A 所需的时间应该是 (6-1)*3+1=16,因为最后一个桶子,不存在等待时间。

YZ[H~6P)2R}Z(3X[UA~IAUL.png

  1. 接下来我们添加些其他任务

image.png

可以看到 C 其实并没有对总体时间产生影响,因为它被安排在了其他任务的冷却期间;而 B 和 A 数量相同,这会导致最后一个桶子中,我们需要多执行一次 B 任务,现在我们需要的时间是 (6-1)*3+2=17

前面两种情况,总结起来:总排队时间 = (桶个数 - 1) * (n + 1) + 最后一桶的任务数

  1. 当冷却时间短,任务种类很多时

image.png

比如上图,我们刚好排满了任务,此时所需时间还是 17,如果现在我还要执行两次任务 F,该怎么安排呢?

image.png

此时我们可以临时扩充某些桶子的大小,插进任务 F,对比一下插入前后的任务执行情况:

**插入前:ABC | ABC | ABD | ABD | ABD | AB

插入后:ABCF | ABCF | ABD | ABD | ABD | AB**

我们在第一个、第二个桶子里插入了任务F,不难发现无论再继续插入多少任务,我们都可以类似处理,而且新插入元素肯定满足冷却要求

继续思考一下,这种情况下其实每个任务之间都不存在空余时间,冷却时间已经被完全填满了。

也就是说,我们执行任务所需的时间,就是任务的数量

这样剩下就很好处理了,我们只需要算两个数:

  1. 记录最大任务数量 N,看一下任务数量并列最多的任务有多少个,即最后一个桶子的任务数 X,计算 NUM1=(N-1)*(n+1)+x

  2. NUM2=tasks.size()

输出其中较大值即可

因为存在空闲时间时肯定是 NUM1 大,不存在空闲时间时肯定是 NUM2>=NUM1


int leastInterval(vector<char>& tasks, int n) {

        int len=tasks.size();

        vector<int> vec(26);

        for(char c:tasks) ++vec[c-'A'];

        sort(vec.begin(),vec.end(),[](int& x,int&y){return x>y;});

        int cnt=1;

        while(cnt<vec.size()&&vec[cnt]==vec[0]) cnt++;

        return max(len,cnt+(n+1)*(vec[0]-1) );

    }

时间复杂度 O(nlogn),空间复杂度 O(1)

统计信息

通过次数 提交次数 AC比率
81983 143023 57.3%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言

相似题目

题目 难度
K 距离间隔重排字符串 困难
重构字符串 中等
上一篇:
620-有趣的电影(Not Boring Movies)
下一篇:
623-在二叉树中增加一行(Add One Row to Tree)
本文目录
本文目录