任务调度器
题目:
思路:
【1】基本上只能靠推导:
首先肯定要知道整个数组中每个任务的个数【这里需要循环遍历】,便于找出最大任务的个数 最大任务个数是1: 假设任务是"A",假设个数为x【现在假设是3,用于演示】,假设步长n为3,则必然会出现下列情况 "A"->未知->未知->未知->"A"->未知->未知->未知->"A" ,这个便是最小的容纳量为:(x-1)*(n+1)+1; 最大任务个数是K: 出现"A"和"B"都是最多任务的情况,情况变为 "A"->"B"->未知->未知->"A"->"B"->未知->未知->"A"->"B" 则公式对应变为(x-1)*(n+1)+k,所以这种又适应了上面的那种。 下面分析多种填充情况: 第一种:刚好能填满或者填不满的情况: 就算填不满,那么所需要的总时间也必须是这个【因为规定了间隔时间的】,则有(x-1)*(n+1)+k 第二种:出现能超出的最小容纳数的情况【假设超出3个】: "A"->"B"->未知->未知->"A"->"B"->未知->未知->"A"->"B"->未知->未知->未知 则对应任务必然是【以是出现间隔最长的情况为例】 【"A","A","A","B","B","B","C","C","D","D","E","E","F"】 "A"->"B"->"C"->"D"->"A"->"B"->"C"->"E"->"A"->"B"->"F"->"D"->"E" 所以这种情况基本上都能采用排列来避免任务的间隔时间损耗,故任务时长就是任务的数量即数组的length 所以当任务的数量大于最小容纳数的时候即就是任务的数量了
代码展示:
基于推导出来的数学公式的代码:
class Solution { public int leastInterval(char[] tasks, int n) { if (tasks.length == 0){ return 0; } if (n == 0){ return tasks.length; } int tLen = tasks.length; int[] hash = new int[26]; int maxSize = 0; for (char ch : tasks){ hash[ch - 'A']++; maxSize = Math.max(maxSize,hash[ch - 'A']); } int result = (maxSize-1)*(n+1); for (int count : hash){ if (maxSize == count){ result++; } } return Math.max(tasks.length,result); } }
运行结果:
//执行用时:3 ms, 在所有 Java 提交中击败了47.68%的用户 //内存消耗:42.3 MB, 在所有 Java 提交中击败了68.58%的用户
当然,其实那些限制本质上是为了快点返回,但是我发现在提交测试的时候发现了,没有判断条件运行时间更快【只能说笑死个人,所以说没必要的提前返回貌似不怎么有用】:
//执行用时:2 ms, 在所有 Java 提交中击败了82.59%的用户 //内存消耗:42.6 MB, 在所有 Java 提交中击败了38.18%的用户 class Solution { public int leastInterval(char[] tasks, int n) { int tLen = tasks.length; int[] hash = new int[26]; int maxSize = 0; for (char ch : tasks){ hash[ch - 'A']++; maxSize = Math.max(maxSize,hash[ch - 'A']); } int result = (maxSize-1)*(n+1); for (int count : hash){ if (maxSize == count){ result++; } } return Math.max(tasks.length,result); } }