任务调度器

问题:
给定一个用字符数组表示的 CPU 需要执行的任务列表。使用 A - Z 表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。

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

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

示例 :
输入:tasks = [“A”,“A”,“A”,“B”,“B”,“B”],n = 2
输出:8
解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B.



分析:
两个相同的任务之间必须有长度为 n 的冷却时间,我们可以将 n+1 个任务看作 CPU 的一轮执行,并且在一轮执行中,n+1 个任务必须是不同的,才能保证相同任务之间至少有 n 的冷却时间。

因为每个任务都有 n 的冷却时间,我们可以让任务数量最多的那个任务首先开始执行,这样可以减少空闲时间。

例:
tasks = [“A”,“A”,“B”,“C”],n = 2
如果 “B” 先执行,执行结果 “B -> A -> C -> 空闲 -> A”
如果 “A” 先执行,执行结果 “A -> B -> C -> A”

我们需要对任务进行统计,并按照任务数量的多少进行排序,从数量最多的任务开始执行,依次执行 n+1 个任务,每次执行一个任务,对应的任务数量需要减一,当没有任务可以执行时,用空闲时间代替。执行完 n+1 个任务后,按照任务数量重新排序,继续执行 n+1 个任务,直到任务全部执行完毕。
代码如下:

public int leastInterval(char[] tasks, int n) {
        int map[] = new int[26];
        // 对任务个数进行统计
        for(char t : tasks)
            map[t-'A'] += 1;
        Arrays.sort(map);	// 对任务进行升序排序
        int times = 0;
        while(map[25] > 0) {
            int i = 0;	// i 表示一轮任务中已执行的任务数量
            while(i <= n) {
            	// 当任务数量最多的那个任务为 0 时,意味着这是最后一轮任务
            	// 此时无需考虑冷却时间(只需要将剩下未执行完的任务执行即可)
                if(map[25] == 0)
                    break;
                // 如果存在可以执行的任务,执行该任务,并将该任务数量减一
                // 如果不存在可执行的任务,times直接加一,表示空闲时间
                if(i < 26 && map[25-i] > 0)
                    map[25-i]--;
                // times 表示执行任务消耗的秒数
                times++;
                i++;
            }
            Arrays.sort(map);
        }
        return times;
    }


假设现有任务 { “A”,“A”,“A” },冷却时间为 3,那么 CPU 执行完该过程需要的时间 times = 2 x (3 + 1) + 1,执行前两个 “A” 需要冷却时间 3 ,执行最后一个 “A”,不需要考虑冷却时间。

那么,假设任务 “A” 的个数最多,且个数为 n ,冷却时间为 p 时,CPU 执行需要的时间 times = (n - 1) x (p + 1) + 1。

此时的空闲时间为 (n - 1) x p,我们可以将其他的任务填补到空闲时间中。当其他任务全部填补到空闲时间,还有剩余的空闲时间,CPU 的执行时间 times = 剩余空闲时间 + 总任务数;当空闲时间全部被填补,还有剩余任务时,CPU 的执行时间为总任务数。

ABCD
ABCD
ABC
ABD

上图的空闲时间没有被填满,因此,CPU 的执行时间 times = 14 + 1 = 15(剩余空闲时间 = 1,总任务数 = 14)。
代码如下:

public int leastInterval(char[] tasks, int n) {
        int map[] = new int[26];
        for(char t : tasks)
            map[t-'A'] += 1;
        Arrays.sort(map);
        int max = map[25] - 1;
        // freeTime表示空闲时间
        int freeTime = max * n;
        for(int i = 0; i < 25; i++) {
            freeTime -= Math.min(map[i],max);
        }

        if(freeTime > 0)
            return freeTime + tasks.length;
        else
            return tasks.length;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值