621. Task Scheduler
问题描述:
Given a char array representing tasks CPU need to do. It contains capital letters A to Z where different letters represent different tasks.Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle.
However, there is a non-negative cooling interval n that means between two same tasks, there must be at least n intervals that CPU are doing different tasks or just be idle.
You need to return the least number of intervals 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.
Note:
- The number of tasks is in the range [1, 10000].
- The integer n is in the range [0, 100].
解题思路:
我们可以首先统计每个人物出现的次数,然后首先安排次数最多的任务。
我们可以用优先队列来帮助我们进行选择次数最多的任务。
因为至少要隔n个时间单位,说明在n+1个时间单位内不能有重复,所以可以不断从队列里取出。
选取万一个block(也就是n+1)个时间单位后,我们要将新的出现次数重新压入优先队列中。
所以可以用一个数组来存储。
看了Grandyang整理的方法中还有别的更快的方法。
这里只copy了一个
代码:
用优先队列的方法:
class Solution { public: int leastInterval(vector<char>& tasks, int n) { unordered_map<char,int> m; for(char c:tasks){ m[c]++; } priority_queue<int> q; for(auto p : m){ q.push(p.second); } int ret = 0; while(!q.empty()){ int cnt = 0; vector<int> temp; for(int i = 0; i <= n; i++){ if(!q.empty()){ temp.push_back(q.top()); q.pop(); cnt++; } } for(int i = 0; i < temp.size(); i++){ if(--temp[i] > 0) q.push(temp[i]); } ret += q.empty() ? cnt : n+1; } return ret; } };
更快的方法:
对于整个安排来说,以出现次数最多(max次)的字母开头后面跟着其他字母的长度为n+1的block会出现max-1次。
因为我们不能保证最后一个block一定会被填满。
最后一个block中应该存着出现次数等于max次的任务。
注意最后返回的是
max(len, (mx - 1) * (n + 1) + 25 - i)
因为我们的排列长度至少要等于给我们的任务个数
class Solution { public: int leastInterval(vector<char>& tasks, int n) { vector<int> cnt(26, 0); for (char task : tasks) { ++cnt[task - 'A']; } sort(cnt.begin(), cnt.end()); int i = 25, mx = cnt[25], len = tasks.size(); while (i >= 0 && cnt[i] == mx) --i; return max(len, (mx - 1) * (n + 1) + 25 - i); } };