原题:
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个时间片,求完成任务集的任务最少需要多少时间片。
题目中给出的例子是: tasks = [‘A’,’A’,’A’,’B’,’B’,’B’], n = 2。完成的最少时间片的情况是: A -> B -> idle -> A -> B -> idle -> A -> B。链中不能出现A -> B -> A……的情况,是因为同类任务A必须中间至少相隔2个任务。
很明显,这是一道关于贪心算法的题目。贪心的策略是:尽可能少地让计算机闲着,即尽可能少地出现链中idle的情况。题目要求,在每一轮n+1个时间间隙中,不能出现相同的任务。如果一次能有(n+1)个不同任务排成一个任务集,那么这个这个任务集是完美的,因为从这个任务集到下一个任务集,中间不需要出现idle,即计算机没有闲着的时刻。那么,接下来的问题,如果在每一轮n+1个时间间隙中,能够选择的不同种类的任务的个数,大于n+1,那么优先选择哪些任务呢?很明显,我们要优先选择那些数量多的任务,这里用到的也是贪心。比如,tasks = [‘A’,’A’,’A’,’B’,’C’,’D’], n = 2。那么完成任务的最小时间链是:A -> B -> C -> A -> D -> idle -> A,答案为7。而不是 B -> C -> D-> A -> idle -> idle -> A -> idle -> idle -> A,答案为10。在任何情况下,我们都要把任务数量多的种类的任务最优先安排,这样是为了避免到最后只剩下单独一个任务的时候消耗太多的 idle。
代码:
class Solution {
public:
int leastInterval(vector<char>& tasks, int n) {
//定义长度为26的vector来存储每个tasks需要重复的次数
vector<int>Letters(26,0);
//统计
for(int i=0;i<tasks.size();i++)
Letters[tasks[i]-'A']++;
//排序
sort(Letters.begin(),Letters.end());
//最少需要用到的时间
int minInterval=0;
//在贪心的策略下,每一步用到的时间
int perInterval=0;
//作为一个标志,判断每一步是否有新的未完成的任务
bool flag=false;
while(1){
perInterval=0;
//查找在贪心的策略下,每一步要完成的任务
for(int i=25;i>=0;i--){
if(Letters[i]>0){
perInterval++;
Letters[i]--;
flag=true;
}
if(perInterval>n)
break;
}
sort(Letters.begin(),Letters.end());
if(flag){
//每一步完成的不重复任务大于n的情况,即不需要空闲时间等的情况
if(perInterval>n)
minInterval+=perInterval;
else{
//如果已经是最后一步,就不需要再空出时间时间来等
if(Letters[25]==0)
minInterval+=perInterval;
//若不是最后一步,要等够n+1时间才能继续进行下一步
else
minInterval+=(n+1);
}
}else{
//若不存在flag=false,说明任务已经全部被完成
break;
}
flag=false;
}
return minInterval;
}
};