给你一个整数数组 ranks ,表示一些机械工的 能力值 。ranksi 是第 i 位机械工的能力值。能力值为 r 的机械工可以在 r * n2 分钟内修好 n 辆车。
同时给你一个整数 cars ,表示总共需要修理的汽车数目。
请你返回修理所有汽车 最少 需要多少时间。
注意: 所有机械工可以同时修理汽车。
示例 1:
输入: ranks = [4,2,3,1], cars = 10
输出: 16
解释:
- 第一位机械工修 2 辆车,需要 4 * 2 * 2 = 16 分钟。
- 第二位机械工修 2 辆车,需要 2 * 2 * 2 = 8 分钟。
- 第三位机械工修 2 辆车,需要 3 * 2 * 2 = 12 分钟。
- 第四位机械工修 4 辆车,需要 1 * 4 * 4 = 16 分钟。
16 分钟是修理完所有车需要的最少时间。
示例 2:
输入: ranks = [5,1,8], cars = 6
输出: 16
解释:
- 第一位机械工修 1 辆车,需要 5 * 1 * 1 = 5 分钟。
- 第二位机械工修 4 辆车,需要 1 * 4 * 4 = 16 分钟。
- 第三位机械工修 1 辆车,需要 8 * 1 * 1 = 8 分钟。
16 分钟时修理完所有车需要的最少时间。
提示:
1 <= ranks.length <= 10^51 <= ranks[i] <= 1001 <= cars <= 10^6
思路
本题我们可以用二分查找求解。我们假设在时间 t 内可以修完所有车辆,那大于 t 的时间都可以修完,如果 t 时间内无法修完所有车辆,那小于 t 的时间内都无法修完。我们可以用二分查找修完所有车辆的最小时间 t。二分查找的下限为 1,上线可以设为让第一个人修完所有车辆用的时间。
如何判断时间 t 内是否可以修完所有车辆内?我们只需要计算所有人在时间 t 内可以修的车辆数向下取整求和。如果和大于等于 cars,就可以修完,如果小于 cars,就修不完。
由于修车工可能会很多,但他们的能力值比较集中(1 - 100),我们可以统计 1 - 100 每个能力值对应的修车工数量,做上面判断的时候就不用遍历每个修改车工了,只需要遍历 1 - 100 计算出对应能力值在 t 时间内可以修车数在乘以修车工数量即可。
解题
/**
* @param {number[]} ranks
* @param {number} cars
* @return {number}
*/
var repairCars = function (ranks, cars) {
const map = new Map();
for (let x of ranks) {
map.set(x, (map.get(x) || 0) + 1);
}
const arr = Array.from(map);
let l = 1;
let r = ranks[0] * cars * cars;
const check = (m) => {
let count = 0;
for (let [x, c] of arr) {
count += Math.floor(Math.sqrt(m / x)) * c;
}
return count >= cars;
};
while (l < r) {
const m = Math.floor((l + r) / 2);
if (check(m)) {
r = m;
} else {
l = m + 1;
}
}
return l;
};