这道题主要是找规律,优化的时候能够采用贪心算法的思想。
<!-- more -->java
给定一个用字符数组表示的 CPU 须要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不一样种类的任务。任务能够以任意顺序执行,而且每一个任务均可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内均可以执行一个任务,或者在待命状态。git
然而,两个相同种类
的任务之间必须有长度为 n 的冷却时间,所以至少有连续 n 个单位时间内 CPU 在执行不一样的任务,或者在待命状态。github
你须要计算完成全部任务所须要的最短期
。算法
示例 1:segmentfault
输入: tasks = ["A","A","A","B","B","B"], n = 2 输出: 8 执行顺序: A -> B -> (待命) -> A -> B -> (待命) -> A -> B.
注:数组
原题url:https://leetcode-cn.com/probl...优化
这道题的思路,正向推导的话,其实就是优先排出现次数多的任务,根据间隔 n ,填充任务,直到全部任务的次数最终都减为0。url
所以,咱们能够用数组存储任务的总次数(由于用大写英文字母表示任务,那就表明最多只能有26种任务),排序以后,按照间隔 n ,从大到小取任务,取完后,再对数组排序,重复上述取任务的过程,直到数组的最大值为0。spa
接下来咱们看看代码:code
public class Solution { public int leastInterval(char[] tasks, int n) { // 将task放入数组中 int[] countArray = new int[26]; for (char task: tasks) { countArray[task - 'A']++; } // 从小到大,进行排序 Arrays.sort(countArray); // 最终耗时 int time = 0; // 从大到小开始遍历 while (countArray[25] > 0) { // 每次遍历前n个数 int i = 0; while (i <= n) { // 说明全部任务已经执行完成 if (countArray[25] == 0) { break; } // 遍历 if (i < 26 && countArray[25 - i] > 0) { countArray[25 - i]--; } // 耗时+1 time++; // 更换任务 i++; } // 从小到大排序 Arrays.sort(countArray); } return time; } }
提交OK,但执行时间上确实不太好,只战胜了47.62%
的 java 执行时间,其时间复杂度为O(time)
, time 表明最终的执行时间。
咱们再来想一想这道题,影响最终执行时间的,有两个因素,一个是任务中出现的最大次数,另外一个就是间隔 n 了。
若是咱们站在最多任务的角度,来看这个问题,假设其最大次数为 maxCount,那么该任务所需的最短执行时间为(maxCount - 1) * (n + 1) + 1
,若是还有其余 i 个和 maxCount 相同次数的任务,那么须要在最终的结果上再加上 i。
那么上面求出来的就是正确答案了吗?
并非,由于上面的最短期,是当剩余时间片可以塞满任务数小于 maxCount 的全部任务。假设 n 很小,那么剩余任务确定须要在任务数等于 maxCount 的那些任务执行完以后,还要继续执行。
但由于最大任务已经能够知足在间隔时间内执行完,那么出现次数小于 maxCount 的任务,确定能够连续执行完成的,也就是不须要空闲等待时间。那么此时的最短执行时间也就是总任务数了。
接下来咱们看看代码:
public class Solution { public int leastInterval(char[] tasks, int n) { if (tasks.length == 0 || n == 0) { return tasks.length; } // 将task放入数组中 int[] countArray = new int[26]; for (char task : tasks) { countArray[task - 'A']++; } // 从小到大,进行排序 Arrays.sort(countArray); // 获取最大次数 int maxCount = countArray[25]; // 若是其余次数都比maxCount小的话,求出针对maxCount的最短期 int result = (maxCount - 1) * (n + 1); // 遍历countArray for (int i = 25; i >= 0; i--) { // 若是有和maxCount相同的,则执行时间+1 if (countArray[i] == maxCount) { result++; } // 不然,直接结束 else { break; } } // 若是总任务数比理论上的最短期长,说明任务不少,但能够把每一个桶填满,所以最短期也就是总任务数 return Math.max(result, tasks.length); } }
提交OK ,在全部 Java 提交中击败了100.00%
的用户,确实快了不少。其时间复杂度为O(M)
,M 表明总任务数。
以上就是这道题目个人解答过程了,不知道你们是否理解了。这道题主要是找规律,优化的时候能够采用贪心算法的思想。
有兴趣的话能够访问个人博客或者关注个人公众号、头条号,说不定会有意外的惊喜。
公众号:健程之道