LeetCode 2335. 装满杯子需要的最短总时长

【LetMeFly】2335.装满杯子需要的最短总时长

力扣题目链接:https://leetcode.cn/problems/minimum-amount-of-time-to-fill-cups/

现有一台饮水机,可以制备冷水、温水和热水。每秒钟,可以装满 2不同 类型的水或者 1 杯任意类型的水。

给你一个下标从 0 开始、长度为 3 的整数数组 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 == 3
  • 0 <= amount[i] <= 100

写在前面:

这道题与LeetCode 1753. 移除石子的最大得分

非常类似,也可以参考1753的题解:https://leetcode.letmefly.xyz/2022/12/21/LeetCode 1753.移除石子的最大得分/

方法一:贪心 + 模拟

每次在三个数里面取最大的两个,接满这两个中不为0的那个,直到这三个数全部为0。

方法二:贪心 + 数学

有没有在方法一的基础上,更快地计算出结果的方法呢?

不失一般性,我们对这三个数排个序,令 a m o u n t [ 0 ] ≤ a m o u n t [ 1 ] ≤ a m o u n t [ 2 ] amount[0]\leq amount[1]\leq amount[2] amount[0]amount[1]amount[2],并将排序后的这三个数分别记为 a a a b b b c c c

1. 假设c足够大

那么我们优先以这样的顺序接水:

  1. 同时接满一杯 a a a c c c直到 a a a接够
  2. 同时接满一杯 b b b c c c直到 b b b接够

因为 c c c是足够大的,所以在接够 a a a和接够 b b b后, c c c还需要再接 c − a − b c-a-b cab杯。

因此总次数就等于 a + b + ( c − a − b ) = c a+b+(c-a-b)=c a+b+(cab)=c

相当于是每次都往 c c c里面倒水,在 a a a b b b没接完的时候附带着给 a a a b b b也接了。

此时有 a + b < c a+b<c a+b<c

2. 假设c没有那么大

也就是说 a + b ≥ c a+b\geq c a+bc的时候,我们每次仍然从数量最大的两个数中选择,那么最终的结果要么是 0 , 0 , 0 0, 0, 0 0,0,0,要么是 0 , 0 , 1 0, 0, 1 0,0,1(或 0 , 0 , 1 0,0,1 0,0,1的其他顺序)。这里的“最终”是指,在“只同时接一杯水”之前的空杯状态。

这是因为:

  • 首先, c c c需要量最多,并且 c c c不足以消耗完 a b ab ab后仍有剩余( a + b ≥ c a+b\geq c a+bc),那么就不可能出现 0 , 0 , 2 0, 0, 2 0,0,2的情况
  • 其次,假设能出现 0 , 1 , 1 0, 1, 1 0,1,1的情况,那么我们就能从两个 1 1 1中各取一杯接满,这样就变成了 0 , 0 , 0 0, 0, 0 0,0,0

综上,假如 a + b ≥ c a+b\geq c a+bc,那么最终至多剩下1个空杯子,也就是说几乎全部是“同时接两杯水”,至多一次接水操作是“只接了一杯水”,因此总接水次数是 ⌈ a + b + c 2 ⌉ \lceil \frac{a+b+c}{2} \rceil 2a+b+c

1和2总结

首先对三种杯子排序使得 a < b < c a<b<c a<b<c

  • a + b < c a+b<c a+b<c,则需要接水 c c c

  • 否则需要接水 ⌈ a + b + c 2 ⌉ \lceil\frac{a+b+c}{2}\rceil 2a+b+c

  • 时间复杂度 O ( 1 ) O(1) O(1),三个数的排序时空消耗可以忽略不计

  • 空间复杂度 O ( 1 ) O(1) O(1)

AC代码

备注: ⌈ a + b + c 2 ⌉ = ⌊ a + b + c + 1 2 ⌋ \lceil\frac{a+b+c}{2}\rceil=\lfloor\frac{a+b+c+1}{2}\rfloor 2a+b+c=2a+b+c+1

C++
class Solution {
public:
    int fillCups(vector<int>& amount) {
        sort(amount.begin(), amount.end());
        if (amount[0] + amount[1] <= amount[2])
            return amount[2];
        return (amount[0] + amount[1] + amount[2] + 1) / 2;
    }
};
Python
class Solution:
    def fillCups(self, amount: List[int]) -> int:
        amount.sort()
        if amount[0] + amount[1] <= amount[2]:
            return amount[2]
        return (amount[0] + amount[1] + amount[2] + 1) // 2

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/128980819

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Tisfy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值