LCP 33. 蓄水

220 阅读1分钟

给定 N 个无限容量且初始均空的水缸,每个水缸配有一个水桶用来打水,第 i 个水缸配备的水桶容量记作 bucket[i]。小扣有以下两种操作:

  • 升级水桶:选择任意一个水桶,使其容量增加为 bucket[i]+1
  • 蓄水:将全部水桶接满水,倒入各自对应的水缸

每个水缸对应最低蓄水量记作 vat[i],返回小扣至少需要多少次操作可以完成所有水缸蓄水要求。

注意:实际蓄水量 达到或超过 最低蓄水量,即完成蓄水要求。

示例 1:

输入:bucket = [1,3], vat = [6,8]

输出:4

解释: 第 1 次操作升级 bucket[0]; 第 2 ~ 4 次操作均选择蓄水,即可完成蓄水要求。

1616122992-RkDxoL-vat1.gif

示例 2:

输入:bucket = [9,0,1], vat = [0,2,2]

输出:3

解释: 第 1 次操作均选择升级 bucket[1] 第 2~3 次操作选择蓄水,即可完成蓄水要求。

提示:

  • 1 <= bucket.length == vat.length <= 100
  • 0 <= bucket[i], vat[i] <= 10^4

题解:

/**
 * @param {number[]} bucket
 * @param {number[]} vat
 * @return {number}
 */
// 方法一:
var storeWater = function (bucket, vat) {
    let max = Math.max(...vat);
    if (max === 0) {
        return 0;
    }
    // 求蓄水次数为op时的总操作数
    // 打水op次 对应 upgrades 桶需要升级次数
    let ops = (op) => {
        let upgrades = 0;
        for (let i = 0; i < vat.length; i++) {
            // 桶需要升级的次数
            upgrades += Math.max(0, Math.ceil(vat[i] / op) - bucket[i]);
        }
        return upgrades + op;
    }
    // 遍历蓄水次数,求总操作次数的最小值
    // 当op大于minOp时,ops(op)必定大于minOp,故可用minOp作为循环结束点
    let minOp = Infinity;
    let op = 0;
    // 依次遍历 op => 打水次数
    while (op < minOp) {
        op++;
        minOp = Math.min(minOp, ops(op));
    }
    return minOp;
};
// 方法二:
var storeWater = function (bucket, vat) {
    // 去掉水缸容量为0的情况 
    if (vat.includes(0)) {
        bucket.splice(vat.indexOf(0), 1)
        vat.splice(vat.indexOf(0), 1)
    }
    // 计算 每一个水桶完成蓄水的次数 
    let arr = bucket.map((v, i) => {
        if (bucket[i] === 0) {
            return vat[i] + 1
        } else {
            return Math.ceil(vat[i] / bucket[i]);
        }
    });
    // 当数组长度不存在时,说明水缸容量都为0 
    if (!arr.length) return 0;
    // 找出数组arr中最大次数 , 设立count为升级桶的次数 
    let max = Math.max(...arr), count = 0;
    let maxIndex = arr.indexOf(max);
    // 假设最小次数 
    let minCount = max + count;
    // 当升级次数小于max
    while (count < max) {
        // 升级水桶 
        bucket[maxIndex]++;
        count++;
        arr[maxIndex] = Math.ceil(vat[maxIndex] / bucket[maxIndex]);
        max = Math.max(...arr);
        minCount = Math.min(max + count, minCount)
        maxIndex = arr.indexOf(max);
    }
    return minCount
};