题目大意:提供k个任务,这些任务没有依赖关系(即可以任意调度)。CPU完成一个任务需要耗时一个时间片段,当执行完一个任务后,相同的任务必须在n个时间片段才能得以执行。请问CPU通过调度最快能在多少时间片段内完成所有任务。


  有难度的一道题目。我借鉴了https://discuss.leetcode.com/topic/92852/concise-java-solution-o-n-time-o-26-space的思路。下面按照我个人理解进行说明:

  首先我们将任务进行分组,相同的任务分入一组。对于T类任务,我们记N(T)为任务T所在分组包含的任务数,读作T的提交数。这里记m为所有类型任务中最大提交数,s为提交数为m的任务类型的总数目。

  最终结果r显然不可能小于任务总数k,并且也肯定不会小于(m-1)*(n+1)+s。这里稍微说明下这个公式的含义。首先我们取任意一个提交数为最大提交数的任务类型T,令其在第一个时间片段中执行第一次,那么显然最后一次必定是在(m-1)*(n+1)时间片段之后执行的,当其在(m-1)*(n+1)+1时间片段执行了最后一次,那么T类型任务占用的时间片必定为1,n+2,2n+3,...,(m-1)*(n+1)+1,其是紧密排列的。而对应的要完成所有提交数为m的s个任务类型,我们最少也需要(m-1)*(n+1)+s个时间片段。

  因此如果我们能找到一个有效的调度方式使得CPU能在max(k, (m-1)*(n+1)+s)的时间片段内完成所有任务,那么这个调度方式必定是最优的(因为不可能存在更快的调度方式)。接下来说明如何利用这些时间片段完成所有任务。

  接下来描述一个构造性的算法:首先我们对将被执行的任务分隔为m个分块,用序号0,...,m-1来标志。每个任务块的前s个任务均为提交数为m的任务。对于其余未被调度的任务,我们将其按照任务种类进行排序(保证同类任务连续被调度),之后遍历所有剩余未被调度的任务,对于第i个任务,我们将其分配在第i%(m-1)的任务分块中,并追加到该任务分块中的后续第一个时间片段中。接着对于所有包含少于n+1个任务的任务块,我们在尾部追加空事件(IDLE),直到其长度刚好达到n+1。最后将这些分块按编号顺序连接起来,得到的就是整个调度序列。

  我们先说明这个调度算法得到的调度序列是有效的,即每个同种类任务的执行的时间片段都最少相隔n。显然对于提交数为m的任务,是满足这个约束的,接下来只需要考虑所有提交数少于m的任务。假设两个F类任务违反了约束,其必定是被调度到了同一任务块中,假设二者在排序序列中的下标为i和j,由i%(m-1)=j%(m-1)可知i-j=z(m-1),而i不等于j,故|i-j|>=m-1,即F种类的任务提交数最少有m个,这与前提相悖,故所有提交数少于m的任务都是不冲突的。

  再说明调度算法所导出的结果的长度为max(k, (m-1)*(n+1)+s)。考虑两种情况,一种是任务块长度不足需要我们补充IDLE,这时候的总共花费的时间片段为(m-1)*(n+1)+s。另外一种就是任务块长度足够甚至超出,此时由于没有添加IDLE,整个导出的序列都是由有效任务组成的,此时导出序列的长度为k。这两种情况下导出序列的上界均为max(k, (m-1)*(n+1)+s),而前面也已经说明过了max(k, (m-1)*(n+1)+s)是最终结果的下界,故最终结果必然为max(k, (m-1)*(n+1)+s)。

  由于我们并真正对任务进行调度,而只是求max(k, (m-1)*(n+1)+s),其中求s和m的时间复杂度为O(n),故总的时间复杂度为O(n),而要保存每个任务类型的提交数,需要O(26)的空间复杂度。 


  最后提供代码:

  1. class Solution {
  2. public int leastInterval(char[] tasks, int n) {
  3. int[] counter = new int[26];
  4. int taskNum = tasks.length;
  5. for(int i = 0; i < taskNum; i++)
  6. {
  7. counter[tasks[i] - 'A']++;
  8. }
  9. int max = 0;
  10. int same = 0;
  11. for(int i = 0; i < 26; i++)
  12. {
  13. if(counter[i] > max)
  14. {
  15. max = counter[i];
  16. same = 1;
  17. }
  18. else if(counter[i] == max)
  19. {
  20. same++;
  21. }
  22. }
  23. return Math.max((max - 1) * (n + 1) + same, taskNum);
  24. }
  25. }

Leetcode:Task Scheduler分析和实现的更多相关文章

  1. [LeetCode] Task Scheduler 任务行程表

    Given a char array representing tasks CPU need to do. It contains capital letters A to Z where diffe ...

  2. Windows Task Scheduler Fails With Error Code 2147943785

    Problem: Windows Task Scheduler Fails With Error Code 2147943785 Solution: This is usually due to a ...

  3. 在Windows Server 2012的Task Scheduler里面配置自动发送邮件

    最近在一台server上配置了每个周末备份数据库的定时任务,想顺手配置发送备份完成的邮件提醒我去Double Check一下备份结果. 悲剧地发现Send an email功能被新版的server给禁 ...

  4. Task Scheduler Error and Success Constants (Windows)

    If an error occurs, the Task Scheduler APIs can return one of the following error codes as an HRESUL ...

  5. 使用C#创建计划任务(How to create a Task Scheduler use C# )

    本文主要讲解了如何使用C#来创建windows计划任务. 需求:在不定时间段运行多个后台程序(winfrom,wpf,console,等等)用于更新数据.  问题:为什么要使用计划任务,而不直接在程序 ...

  6. SpringBoot2 task scheduler 定时任务调度器四种方式

    github:https://github.com/chenyingjun/springboot2-task 使用@EnableScheduling方式 @Component @Configurabl ...

  7. Task Scheduler

    https://technet.microsoft.com/en-us/library/cc748993(v=ws.11).aspx#BKMK_winui If Task Scheduler is n ...

  8. Spring的任务调度@Scheduled注解——task:scheduler和task:executor的解析

    原文地址: https://blog.csdn.net/yx0628/article/details/80873774 一个简单的Spring定时任务的 demo,全部代码见下载地址:https:// ...

  9. Task Scheduler API Error 80041318

    https://stackoverflow.com/questions/42307917/task-scheduler-api-error-80041318/42462235#42462235 Hi ...

随机推荐

  1. Android 进阶7:进程通信之 AIDL 的使用

    读完本文你将了解: AIDL 是什么 AIDL 支持的数据类型 AIDL 如何编写 AIDL 实例 创建 AIDL 编写服务端代码 编写客户端代码 运行结果 总结 代码地址 Thanks 记得 201 ...

  2. hihocoder-1486物品价值(状压dp)

    题目链接: 物品价值 小Hi现在有n个物品,每个物品都有一个价值.并且这n个物品总共有m个不同的属性,每个物品都具有其中若干属性. 小Ho要从中选出若干物品,满足每个属性都正好有奇数个物品拥有,且被选 ...

  3. 毕业生、程序猿转岗该如何选择Java、大数据和VR?

    许久不见的朋友请我吃饭,期间给我介绍他一个弟弟,说明年要毕业了,还不知道找啥工作,说有培训机构让他学VR.大数据什么的,不知道前景咋样,想咨询一下我.相信很多朋友面临毕业,都不知道该从事哪个行业,自己 ...

  4. 使用macbook破解WPA/WPA2 wifi密码

    文本仅供学习交流. 我使用的系统是macbook pro 15: 安装aircrack-ng 使用homebrew安装,命令: brew install aircrack-ng 抓包-抓取带密码的握手 ...

  5. python学习之控制语句

    #if statement number=int(input("please input a number")); if number<10 : print("is ...

  6. Mybatis与Hibernate的详细对比

    前言 这篇博文我们重点分析一下Mybatis与hibernate的区别,当然在前面的博文中我们已经深入的研究了Mybatis和Hibernate的原理. Mybatis [持久化框架]Mybatis简 ...

  7. 【HTML5】Canvas绘图详解-1

    ----->Canvas绘制基础 1,线条绘制 1-1,线条组成的图形和beginPath 案例:绘制由不同颜色的线条组成的图案 1-2,多边形的填充和closePath 案例:绘制封闭具有填充 ...

  8. 【CSS3】 - 初识CSS3

    .navdemo{ width:560px; height: 50px; font:bold 0/50px Arial; text-align:center; margin:40px auto 0; ...

  9. Volley的post使用

    直接看代码,注意在manifest中加入Internet权限 <uses-permission android:name="android.permission.INTERNET&qu ...

  10. 【转】c# 判断指定文件是否存在

    private void button2_Click(object sender, EventArgs e) { if (File.Exists(@"E:\exists.txt") ...