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

题目

现有一台饮水机,可以制备冷水、温水和热水。每秒钟,可以装满 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)
链接:https://leetcode.cn/problems/minimum-amount-of-time-to-fill-cups
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法

1.模拟
在循环内次做一次操作,该操作取一个最大值和另一个任意的值,进行减一

public static int fillCups(int[] amount) {
        int time = 0;
        while (true)
        {
            if(amount[0]==0&& amount[1]==0 && amount[2]==0)
            {
                break;
            }
            time++;
            int maxIndex=getMaxIndex(amount);
            amount[maxIndex]--;
            if(maxIndex==0)
            {
                if(amount[1]>0)
                {
                    amount[1]--;
                }else if(amount[2]>0)
                {
                    amount[2]--;
                }
            }
            if(maxIndex==1)
            {
                if(amount[0]>0)
                {
                    amount[0]--;
                }else if(amount[2]>0)
                {
                    amount[2]--;
                }
            }
            if(maxIndex==2)
            {
                if(amount[0]>0)
                {
                    amount[0]--;
                }else if(amount[1]>0)
                {
                    amount[1]--;
                }
            }
        }
        return time;
    }
    public static int getMaxIndex(int[] amount)
    {
        if(amount[0]>=amount[1] && amount[0]>=amount[2] )
        {
            return 0;
        }
        if(amount[1]>=amount[0] && amount[1]>=amount[2])
        {
            return 1;
        }
        if(amount[2]>=amount[0] && amount[2]>=amount[1])
        {
            return 2;
        }
        return 0;
    }

2.分类讨论
1.先排序找出最大的数字,令x=amount[0],y=amount[1],z=amount[2]分两种情况:(1)x+y<=z(2)x+y=z;
第一种情况时间就为z次。
第二种情况,又分两种情况,令t=x+y-z;t为x+y超过z的次数。每次可消两个。由此当消除超过的t次后,x'+y'=z,此时,需要再进行t次的消除。消除t次用的时间为2/t;这里t为奇偶有两种略微不同的情况。偶数的就是上述规则,奇数的需要消除(t+1)/2,消除后还是需要z次

public static int fillCups2(int[] amount) {
        int time = 0;
        Arrays.sort(amount);
        if(amount[2]>=amount[0]+amount[1])
        {
            return amount[2];
        }
        else {
            //超出的部分
            int t = amount[0]+amount[1]-amount[2];
            if(t%2==0)
            {
                //每次能消2个,先消t/2次,剩余的就是amount[2]=amount[0]+amount[1];
                time=amount[2]+t/2;
            }
            else {
                time = (t + 1) / 2 + amount[2];
            }
            return time;
        }
    }
posted @ 2023-02-11 14:38  花茶冰糖  阅读(51)  评论(0编辑  收藏  举报