Easy
题目描述
你有一个可以分配冷水、温水和热水的饮水机。每一秒钟,你可以:
- 装满 2 杯不同类型的水,或者
- 装满 1 杯任意类型的水。
给你一个长度为 3 的下标从 0 开始的整数数组 amount,其中 amount[0]、amount[1] 和 amount[2] 分别表示需要装满冷水、温水和热水的杯子数量。返回装满所有杯子所需的最少秒数。
示例 1:
输入:amount = [1,4,2]
输出:4
解释:下面是一种方案:
第 1 秒:装满一杯冷水和一杯温水。
第 2 秒:装满一杯温水和一杯热水。
第 3 秒:装满一杯温水和一杯热水。
第 4 秒:装满一杯温水。
可以证明最少需要 4 秒才能装满所有杯子。
示例 2:
输入:amount = [5,4,4]
输出:7
解释:下面是一种方案:
第 1 秒:装满一杯冷水和一杯热水。
第 2 秒:装满一杯冷水和一杯温水。
第 3 秒:装满一杯冷水和一杯温水。
第 4 秒:装满一杯温水和一杯热水。
第 5 秒:装满一杯冷水和一杯热水。
第 6 秒:装满一杯冷水和一杯温水。
第 7 秒:装满一杯热水。
示例 3:
输入:amount = [5,0,0]
输出:5
解释:每秒装满一杯冷水。
提示:
amount.length == 30 <= amount[i] <= 100
解题思路
解题思路
这道题的关键是理解每次可以装满 2 杯不同类型的水或 1 杯任意类型的水,目标是最小化总时间。
贪心策略分析: 为了最小化时间,我们应该尽可能多地利用每次装满 2 杯的机会。每次都选择剩余杯子数最多的两种类型同时装满。
数学分析: 设三种水的杯子数为 a、b、c,不妨设 a ≥ b ≥ c。
我们有两种情况:
- 如果 a ≥ b + c:此时最优策略是先同时装 b 和 c,需要 b + c 秒,然后单独装剩下的 a - (b + c) 杯,总时间为 a 秒。
- 如果 a < b + c:此时可以通过合理安排,让三种水的杯子数尽可能均匀地减少。总杯子数为 a + b + c,每次最多装 2 杯,所以最少需要 ⌈(a + b + c) / 2⌉ 秒。
最终公式:
答案为 max(最大值, ⌈总和 / 2⌉)。
可以用排序或直接求最大值和总和来实现。推荐使用数学公式的方法,时间复杂度最优。
代码实现
class Solution {
public:
int fillCups(vector<int>& amount) {
int maxVal = *max_element(amount.begin(), amount.end());
int sum = amount[0] + amount[1] + amount[2];
return max(maxVal, (sum + 1) / 2);
}
};
class Solution:
def fillCups(self, amount: List[int]) -> int:
max_val = max(amount)
total = sum(amount)
return max(max_val, (total + 1) // 2)
public class Solution {
public int FillCups(int[] amount) {
int maxVal = amount.Max();
int sum = amount.Sum();
return Math.Max(maxVal, (sum + 1) / 2);
}
}
var fillCups = function(amount) {
const maxVal = Math.max(...amount);
const sum = amount.reduce((a, b) => a + b, 0);
return Math.max(maxVal, Math.ceil(sum / 2));
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(1) | 只需要求最大值和总和,常数时间操作 |
| 空间复杂度 | O(1) | 只使用常数额外空间 |