修车的最少时间

45 阅读1分钟

2594. 修车的最少时间 - 力扣(LeetCode)

给你一个整数数组  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^5
  • 1 <= ranks[i] <= 100
  • 1 <= 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;
};