leetcode 621.Task Scheduler

本文深入探讨了CPU任务调度算法,特别是在存在冷却间隔约束的情况下,如何优化任务执行顺序以减少闲置时间。通过实例分析,解释了如何计算完成所有任务所需的最小时间周期,以及在特定条件下如何调整计算公式。

Given a char array representing tasks CPU need to do. It contains capital letters A to Z where different letters represent different tasks. Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle.

However, there is a non-negative cooling interval n that means between two same tasks, there must be at least n intervals that CPU are doing different tasks or just be idle.

You need to return the least number of intervals the CPU will take to finish all the given tasks.

Example:

Input: tasks = [“A”,“A”,“A”,“B”,“B”,“B”], n = 2
Output: 8
Explanation: A -> B -> idle -> A -> B -> idle -> A -> B.

给出一个tasks的数组,代表不同的task,一个周期CPU可以选择处理一个task,也可以闲置
而且处理相同的task的时候,中间必须有n次闲置

比如上面例子中一个A到下一个A之间必须有n=2次闲置

思路:
为了不闲置,尽量每次处理不同的task
比如上面的例子,把不同的task先分组放在一起,一次处理一个由不同task组成的组,在这个组内就不需要闲置
而且每组的顺序应该是一样,这样才能保证相同的task间隔最远

AB AB AB

这样相同的A之间隔了一个B,但是题中要求n=2
也就是两个A之间需要间隔两个周期
因为少了一个,所以补一个idle(闲置),可以看到最后的一组后面是不需要补的
AB(idle)AB(idle)AB

而能留到最后一组的就是frequency最高的几个task
比如[A,A,A,A,B,B,C]
分组后(假设n=2)
ABC AB(idle) A(idle)(idle) A

可以看到需要的时间周期是由最大frequency的task决定的,由于最后一个不需要加idle
所以不看最后一个的时候,需要的时间周期是
(maxFrequency - 1) * (n + 1) //(n+1)是因为还要加上自身task

再加上最后一组,也就是最大frequency的task个数
(maxFrequency - 1) * (n - 1) + maxFrequencyNum

不过还有一种特殊情况,比如分组后task是ABC ABC,而n=1的情况
可以看到相同task间的间隔是>n的,但是如果按上述方法n=1进行计算
结果result就会比task的总个数小,这时候需要取
max(tasksNum, result)

//2ms
    public int leastInterval(char[] tasks, int n) {
        if (tasks == null || tasks.length == 0) {
            return 0;
        }
        
        if (n == 0) {
            return tasks.length;
        }
        
        int[] count = new int[26];
        int maxCount = 0;
        int res = 0;
        int sameFreq = 0;       
        
        for (int i = 0; i < tasks.length; i++) {
            count[tasks[i] - 'A'] ++;
        }
        
        for (int i = 0; i < count.length; i++) {
            if (count[i] > maxCount) {
            	maxCount = count[i];
            };
        }
        
        for (int i = 0; i < count.length; i++) {
            if (count[i] == maxCount) {
            	sameFreq ++;
            };
        }
        
        res = (maxCount - 1) * (n + 1) + sameFreq;
        
        return Math.max(tasks.length, res);
        
    }

用c++就会方便很多
count_if中用到lambda表达式,需要用到前面的max_count,所以放在[max_count]
lambda表达式中也需要加;
另外max比较的时候不能是int类型,所以res的类型是size_t

//48ms
class Solution {
public:
    int leastInterval(vector<char>& tasks, int n) {
        vector<int> count(26, 0);
        
        for (int i = 0; i < tasks.size(); i++) {
            count[tasks[i] - 'A'] ++;
        }
        
        int max_count = *max_element(count.cbegin(), count.cend());
        int same_freq = count_if(count.cbegin(), count.cend(), 
                                 [max_count](int c){return c == max_count;});
        size_t res = (max_count - 1) * (n + 1) + same_freq;
        
        return max(tasks.size(), res);
    }
    
};
### 贪心算法LeetCode 上的应用 贪心算法是一种通过局部最优选择来达到全局最优解的方法。其核心思想是在每一步都做出当前状态下最好的选择,从而希望最终能够得到整体的最优解[^1]。 以下是基于 Python 的几个经典贪心算法题目及其解决方案: --- #### 题目 1: **LeetCode 455. Assign Cookies** 给定两个数组 `g` 和 `s`,分别表示孩子的胃口值和饼干大小。每个孩子最多只能吃一块饼干,求最大满足的孩子数量。 ##### 解法 先对两个数组进行排序,然后从小到大分配饼干给尽可能多的孩子。 ```python def findContentChildren(g, s): g.sort() s.sort() i, j = 0, 0 count = 0 while i < len(g) and j < len(s): if s[j] >= g[i]: count += 1 i += 1 j += 1 return count ``` 此方法利用了贪心策略,在每次循环中优先考虑最小需求的孩子并匹配最合适的饼干[^3]。 --- #### 题目 2: **LeetCode 135. Candy** 有 n 个小孩站在一条直线上,每个小孩有一个评分值。分发糖果的要求是:如果某个小孩的评分高于相邻的小孩,则该小孩获得更多的糖果;至少每人一颗糖果。 ##### 解法 两次遍历数组,一次从前向后,另一次从后向前,确保左右两侧的关系都被满足。 ```python def candy(ratings): n = len(ratings) candies = [1] * n for i in range(1, n): if ratings[i] > ratings[i - 1]: candies[i] = candies[i - 1] + 1 for i in range(n - 2, -1, -1): if ratings[i] > ratings[i + 1]: candies[i] = max(candies[i], candies[i + 1] + 1) return sum(candies) ``` 这种方法通过两轮扫描实现了局部最优条件下的全局最优解。 --- #### 题目 3: **LeetCode 621. Task Scheduler** 给定一组任务字符以及冷却时间 `n`,计算完成所有任务所需的最少单位时间数。 ##### 解法 统计频率最高的任务数目,并根据这些任务之间的间隔安排其他任务。 ```python from collections import Counter def leastInterval(tasks, n): task_counts = list(Counter(tasks).values()) max_freq = max(task_counts) max_count = task_counts.count(max_freq) intervals = (max_freq - 1) * (n + 1) + max_count return max(len(tasks), intervals) ``` 上述代码的关键在于理解如何合理填充高频任务之间的时间间隙。 --- #### 总结 解决贪心类问题时,通常需要明确以下几个方面: - 是否可以通过逐步优化子结构解决问题? - 如何定义“局部最优”,它是否能导向“全局最优”? 此外,清晰表达逻辑流程有助于构建完整的解决方案[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值