leetcode 2141. Maximum Running Time of N Computers(N台计算机的最大运行时间)

在这里插入图片描述
有n台电脑,数组batteries代表每块电池的电量。
每台电脑每次只能放入一块电池,然后电池可以任意交换,但电池不能充电。
所有电脑必须同时运行。
问n台电脑最多可以同时运行几分钟。

思路:

乍一看很复杂,复杂的电池交换方案,但是你不需要考虑具体的电池怎么交换的。
只需要考虑电量够不够支持n台电脑同时运行target分钟。

n台电脑同时运行target分钟所需要的电量是target * n.

但是不能简单地把所有电池的电量相加,因为n台电脑要同时运行,一个电池的电量再多,也不能同时供给多台电脑。
一个电脑获得的电量是min(target, batteries[i]),
target < 一个电池的电量时,只需供target的电量,
target > 电池电量时,只能获得一个电池的最大电量。

如果一个电池电量不够,怎么交换呢。
现在不去考虑具体的交换方案,直接计算所有电池的电量够不够。
因为要n台电脑同时运行,所以计算所有电池能同时供多少电量,即每个电池供电min(target, batteries[i]),计算sum。

当sum > target * n时,电池能满足n台电脑同时运行target分钟,可以把target调大。
当sum > target * n时,电池不能满足n台电脑同时运行target分钟,需要把target调小。

最理想的情况是电池总电量平分,即sum(batteries[i]) / n, 这是target的上限。
因为batteries.length >= n, batteries[i] >=1, 所以target的下限是1.

所以这是一个binary search的方案。
这里要注意left, right和mid的取值,在注释里面标注。

class Solution {
    
    
    public long maxRunTime(int n, int[] batteries) {
    
    
        long sum = 0;
        for(int bat : batteries) sum += bat;
        long left = 1;
        long right = sum / n;

        while(left < right) {
    
    
        //既然用了left=mid,那么mid就要向right一侧靠,用left+(right-left)/2可能会陷入无限循环(left始终=mid)
            long mid = right -  (right - left) / 2;
            if(isValid(n, mid, batteries)) {
    
    
             //用left=mid+1会出问题,就是在sum==target时,mid就是极限的target,用left=mid+1可能会出现left在跳出循环前又增加1.
                left = mid;
            } else {
    
    
                right = mid - 1;
            }
        }
        return left;
    }

    boolean isValid(int n, long target, int[] batteries) {
    
    
        long res = 0;
        for(int bat : batteries) {
    
    
            res += Math.min(target, bat);
        }
        return res >= target*n;
    }
}

猜你喜欢

转载自blog.csdn.net/level_code/article/details/131982044
今日推荐