LeetCode题练习与总结:任务调度器--621

一、题目描述

给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表,用字母 A 到 Z 表示,以及一个冷却时间 n。每个周期或时间间隔允许完成一项任务。任务可以按任何顺序完成,但有一个限制:两个 相同种类 的任务之间必须有长度为 n 的冷却时间。

返回完成所有任务所需要的 最短时间间隔 。

示例 1:

输入:tasks = ["A","A","A","B","B","B"], n = 2

输出:8

解释:

在完成任务 A 之后,你必须等待两个间隔。对任务 B 来说也是一样。在第 3 个间隔,A 和 B 都不能完成,所以你需要待命。在第 4 个间隔,由于已经经过了 2 个间隔,你可以再次执行 A 任务。

示例 2:

输入:tasks = ["A","C","A","B","D","B"], n = 1

输出:6

解释:一种可能的序列是:A -> B -> C -> D -> A -> B。

由于冷却间隔为 1,你可以在完成另一个任务后重复执行这个任务。

示例 3:

输入:tasks = ["A","A","A","B","B","B"], n = 3

输出:10

解释:一种可能的序列为:A -> B -> idle -> idle -> A -> B -> idle -> idle -> A -> B。

只有两种任务类型,A 和 B,需要被 3 个间隔分割。这导致重复执行这些任务的间隔当中有两次待命状态。

提示:

  • 1 <= tasks.length <= 10^4
  • tasks[i] 是大写英文字母
  • 0 <= n <= 100

二、解题思路

  1. 统计每个任务出现的次数,可以使用一个长度为26的数组来记录,因为任务只有A到Z共26种。
  2. 找出出现次数最多的任务,假设其出现次数为maxCount。
  3. 计算最短时间间隔,最短时间间隔至少为 (maxCount - 1) * (n + 1) + 1。这是因为最频繁的任务之间需要有n个冷却时间,而最频繁的任务可以放在序列的开始和结束位置。
  4. 遍历统计数组,找出有多少个任务的出现次数等于maxCount,记为maxCountTasks。
  5. 如果maxCountTasks大于1,那么最短时间间隔就是任务总数,因为最频繁的任务之间至少有一个冷却时间,但如果有多个任务出现次数相同,那么它们可以交替执行,不会有空闲时间。
  6. 如果maxCountTasks小于等于1,那么最短时间间隔是步骤3计算的结果和任务总数之间的较大值,因为可能存在空闲时间。

三、具体代码

class Solution {
    public int leastInterval(char[] tasks, int n) {
        // 步骤1:统计每个任务出现的次数
        int[] taskCounts = new int[26];
        for (char task : tasks) {
            taskCounts[task - 'A']++;
        }
        
        // 步骤2:找出出现次数最多的任务
        int maxCount = 0;
        for (int count : taskCounts) {
            maxCount = Math.max(maxCount, count);
        }
        
        // 步骤3:计算最短时间间隔
        int intervals = (maxCount - 1) * (n + 1);
        
        // 步骤4:找出有多少个任务的出现次数等于maxCount
        int maxCountTasks = 0;
        for (int count : taskCounts) {
            if (count == maxCount) {
                maxCountTasks++;
            }
        }
        
        // 步骤5和6:返回最短时间间隔
        return Math.max(intervals + maxCountTasks, tasks.length);
    }
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 统计每个任务出现的次数:我们需要遍历整个tasks数组,这个数组的大小是m,所以这一步的时间复杂度是O(m)。
  • 找出出现次数最多的任务:我们需要遍历一个固定大小的数组taskCounts,它的大小是26,所以这一步的时间复杂度是O(1),因为遍历一个固定大小的数组的时间复杂度是常数。
  • 再次遍历taskCounts数组来找出有多少个任务的出现次数等于maxCount:这一步的时间复杂度同样是O(1)。

综上所述,整个算法的时间复杂度是O(m),因为O(m)和O(1)相加,时间复杂度由O(m)主导。

2. 空间复杂度
  • taskCounts数组:这个数组的大小是固定的,为26,所以它占用的空间是O(1)。
  • 其他变量:maxCountintervalsmaxCountTasks等都是常数个变量,它们占用的空间是O(1)。

因此,整个算法的空间复杂度是O(1),因为算法使用的额外空间不随输入规模tasks的大小变化。

五、总结知识点

  • 数组的使用:

    • 使用数组taskCounts来统计每个任务出现的次数。
    • 遍历数组来找出最大值和特定条件下的元素数量。
  • ASCII码操作:

    • 通过task - 'A'将字符转换为数组索引,这是因为大写字母A到Z在ASCII码表中是连续的。
  • 循环和条件判断:

    • 使用for循环来遍历任务数组tasks和统计数组taskCounts
    • 使用if语句来判断任务的出现次数是否等于最大出现次数。
  • 基本数学运算:

    • 使用Math.max函数来找出最大值。
    • 使用乘法和加法来计算最短时间间隔。
  • 算法逻辑:

    • 实现了一个贪心算法,通过计算最频繁任务的间隔来确定最短时间间隔。
    • 考虑到最频繁任务之间的冷却时间,以及可能存在的空闲时间。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直学习永不止步

谢谢您的鼓励,我会再接再厉的!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值