Medium
题目描述
给你一个下标从 0 开始的整数数组 tasks ,其中 tasks[i] 表示任务的难度级别。在每一轮中,你可以完成 2 个或者 3 个 相同难度级别 的任务。
请你返回完成所有任务需要的 最少 轮数,如果无法完成所有任务,返回 -1 。
示例 1:
输入:tasks = [2,2,3,3,2,4,4,4,4,4]
输出:4
解释:要完成所有任务,一个可能的计划是:
- 第一轮,你完成 3 个难度级别为 2 的任务。
- 第二轮,你完成 2 个难度级别为 3 的任务。
- 第三轮,你完成 3 个难度级别为 4 的任务。
- 第四轮,你完成 2 个难度级别为 4 的任务。
可以证明,无法在少于 4 轮的情况下完成所有任务,所以答案为 4 。
示例 2:
输入:tasks = [2,3,3]
输出:-1
解释:只有 1 个难度级别为 2 的任务,但每一轮中,你只能完成 2 个或者 3 个相同难度级别的任务。因此,你无法完成所有任务,答案为 -1 。
提示:
1 <= tasks.length <= 10^51 <= tasks[i] <= 10^9
解题思路
这道题的核心是贪心算法。我们需要统计每个难度级别的任务数量,然后计算完成这些任务所需的最少轮数。
关键观察:
- 每轮只能完成2个或3个相同难度的任务
- 如果某个难度级别只有1个任务,则无法完成(返回-1)
- 对于n个相同难度的任务,我们要找到最少轮数
贪心策略: 对于n个任务,我们优先使用3个任务一轮的方式,因为这样效率更高:
- 如果 n % 3 == 0,则需要 n/3 轮
- 如果 n % 3 == 1,则最后4个任务用两轮完成(2+2),总共需要 (n-4)/3 + 2 = (n+2)/3 轮
- 如果 n % 3 == 2,则最后2个任务用一轮完成,总共需要 n/3 + 1 = (n+2)/3 轮
可以发现,当n >= 2时,最少轮数总是 (n + 2) / 3。
算法步骤:
- 使用哈希表统计每个难度级别的任务数量
- 遍历每个难度级别,检查是否可以完成(数量>=2)
- 累加每个难度级别所需的最少轮数
代码实现
class Solution {
public:
int minimumRounds(vector<int>& tasks) {
unordered_map<int, int> count;
for (int task : tasks) {
count[task]++;
}
int rounds = 0;
for (auto& [difficulty, freq] : count) {
if (freq == 1) {
return -1;
}
rounds += (freq + 2) / 3;
}
return rounds;
}
};
class Solution:
def minimumRounds(self, tasks: List[int]) -> int:
count = Counter(tasks)
rounds = 0
for freq in count.values():
if freq == 1:
return -1
rounds += (freq + 2) // 3
return rounds
public class Solution {
public int MinimumRounds(int[] tasks) {
var count = new Dictionary<int, int>();
foreach (int task in tasks) {
count[task] = count.GetValueOrDefault(task, 0) + 1;
}
int rounds = 0;
foreach (int freq in count.Values) {
if (freq == 1) {
return -1;
}
rounds += (freq + 2) / 3;
}
return rounds;
}
}
/**
* @param {number[]} tasks
* @return {number}
*/
var minimumRounds = function(tasks) {
const freq = new Map();
for (const task of tasks) {
freq.set(task, (freq.get(task) || 0) + 1);
}
let rounds = 0;
for (const count of freq.values()) {
if (count === 1) return -1;
rounds += Math.ceil(count / 3);
}
return rounds;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历数组一次进行计数,然后遍历哈希表一次计算轮数 |
| 空间复杂度 | O(k) | k为不同难度级别的数量,最坏情况下为O(n) |
相关题目
. Climbing Stairs (Easy)
. Odd String Difference (Easy)
. Minimum Levels to Gain More Points (Medium)