Leetcode算法学习日志-621 Task Scheduler

Leetcode 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.

题意分析

用大写字母表示多个任务,不同大写字母表示不同任务,每个任务的执行需要一个时隙,两个相同任务之间必须至少相差n个时隙,没有任务的时隙表示为idle。求问怎么安排任务,才能使得所需时隙数最少。

解法分析

本题采用贪心算法。根据题意,相同的任务需要间隔n个时隙以上,因此,使得总时隙长的主要原因就是相同任务需要间隔分布,找到出现次数最多的任务,将其作为框架,这就是本题的贪心选择。假设频数最高的任务频数为k,则框架中有k-1个大间隙,之后依次向间隙中插入频数递减的任务,一次插入一个任务,k-1个间隙轮流插入,这样能保证插入间隙的任务数足够均匀。举例如下:

输入为AAAABBBEEFFGG n=3

  • 首先选频数最高的A作为框架A______A______A_______A,注意框架间隙没有时隙数限制,不一定是n。
  • 找到频数第二的B,依次放入每个时隙,得到AB____AB_____AB_____A。
  • 之后是E,得到ABE___ABE____AB____A。
  • 之后是F,得到ABEF____ABE___ABF____A,注意第一个F是插入第三个间隙的,之后循环插入了第一个间隙。
  • 最后是G,得到ABEF____ABEG___ABFG___A,此时所有元素都放入了,且都满足间隔3以上,则最终得到ABEFABEGABFGA,可以看出,这正好是tasks的长度。

再看第二个例子:输入为ACCCEEE n=2

  • 框架为CE___CE___CE
  • 放入A后为CEACE_CE,这也是最终结果,由于n=2,所以有一个idle,总共时隙为,这个不是tasks长度,而是(n+1)*(freq(CE)-1)+2,其中2为频数最高任务的个数。

下面证明上述算法的正确性。

分两种情况,一是间隙填满,所需时隙数就是任务数,明显是最少时隙数。第二种情况是间隙没填满,所需时隙数为(n+1)*(freq(CE)-1)+k,k为频数最大任务数,如第二个例子,由于每次放入都是循环放入间隙,由于没填满,所以框架的间隙就是n,由此可以求出总共需要的时隙数。C++代码如下:

class Solution {
public:
    static bool compare(int &a,int &b){
        return a>=b;
    }
    int leastInterval(vector<char>& tasks, int n) {
        vector<int> temp(26,0);
        vector<int> number;
        int count=0;
        int i;
        int m=tasks.size();
        for(i=0;i<m;i++)
            temp[tasks[i]-'A']++;
        for(i=0;i<26;i++){
            if(temp[i]!=0)
                number.push_back(temp[i]);     
        }
        sort(number.begin(),number.end(),compare);  
        int rest=0;
        for(auto rr:number){//count the most frequent Char
            if(rr==number[0])
                rest++;
            else
                break;     
        }
        count=max(m,(number[0]-1)*(n+1)+rest);
        return count;      
    }
};



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值