LeetCode 2594: Minimum Time to Repair Cars (Binary Search on Answer)
LeetCode 2594Binary SearchMathToday we solve LeetCode 2594 - Minimum Time to Repair Cars.
Source: https://leetcode.com/problems/minimum-time-to-repair-cars/
English
Problem Summary
Each mechanic with rank r needs r * n² minutes to repair n cars. Given all ranks and total cars, return the minimum time to finish all repairs.
Key Insight
If we fix time t, a mechanic of rank r can repair at most floor(sqrt(t / r)) cars. Summing this across mechanics gives whether t is feasible. Feasibility is monotonic, so binary search applies.
Complexity
Time: O(m log U), where m is mechanics count and U is answer upper bound. Space: O(1).
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public long repairCars(int[] ranks, int cars) {
long left = 1, right = (long) ranks[0] * cars * cars;
for (int r : ranks) right = Math.min(right, (long) r * cars * cars);
while (left < right) {
long mid = left + (right - left) / 2;
if (canFinish(ranks, cars, mid)) right = mid;
else left = mid + 1;
}
return left;
}
private boolean canFinish(int[] ranks, int cars, long t) {
long repaired = 0;
for (int r : ranks) {
repaired += (long) Math.sqrt((double) t / r);
if (repaired >= cars) return true;
}
return false;
}
}func repairCars(ranks []int, cars int) int64 {
left, right := int64(1), int64(ranks[0])*int64(cars)*int64(cars)
for _, r := range ranks {
cand := int64(r) * int64(cars) * int64(cars)
if cand < right {
right = cand
}
}
for left < right {
mid := left + (right-left)/2
if canFinish(ranks, cars, mid) {
right = mid
} else {
left = mid + 1
}
}
return left
}
func canFinish(ranks []int, cars int, t int64) bool {
repaired := int64(0)
for _, r := range ranks {
repaired += int64(math.Sqrt(float64(t / int64(r))))
if repaired >= int64(cars) {
return true
}
}
return false
}class Solution {
public:
long long repairCars(vector<int>& ranks, int cars) {
long long left = 1, right = 1LL * *min_element(ranks.begin(), ranks.end()) * cars * cars;
while (left < right) {
long long mid = left + (right - left) / 2;
if (canFinish(ranks, cars, mid)) right = mid;
else left = mid + 1;
}
return left;
}
bool canFinish(vector<int>& ranks, int cars, long long t) {
long long repaired = 0;
for (int r : ranks) {
repaired += (long long) sqrt((long double)t / r);
if (repaired >= cars) return true;
}
return false;
}
};class Solution:
def repairCars(self, ranks: list[int], cars: int) -> int:
left, right = 1, min(ranks) * cars * cars
def can_finish(t: int) -> bool:
repaired = 0
for r in ranks:
repaired += int((t // r) ** 0.5)
if repaired >= cars:
return True
return False
while left < right:
mid = (left + right) // 2
if can_finish(mid):
right = mid
else:
left = mid + 1
return leftvar repairCars = function(ranks, cars) {
let left = 1n;
let minRank = BigInt(Math.min(...ranks));
let right = minRank * BigInt(cars) * BigInt(cars);
const canFinish = (t) => {
let repaired = 0n;
for (const r of ranks) {
repaired += BigInt(Math.floor(Math.sqrt(Number(t / BigInt(r)))));
if (repaired >= BigInt(cars)) return true;
}
return false;
};
while (left < right) {
const mid = left + (right - left) / 2n;
if (canFinish(mid)) right = mid;
else left = mid + 1n;
}
return Number(left);
};中文
题目概述
技工等级为 r 时,修 n 辆车需要 r * n² 分钟。给定所有技工等级和目标车辆数 cars,求最短完成时间。
核心思路
固定时间 t 后,等级 r 的技工最多可修 floor(sqrt(t / r)) 辆车。把所有技工可修数量相加,就能判断 t 是否可行。可行性随 t 单调,因此可二分答案。
复杂度分析
时间复杂度 O(m log U),其中 m 为技工数,U 为答案上界;空间复杂度 O(1)。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public long repairCars(int[] ranks, int cars) {
long left = 1, right = (long) ranks[0] * cars * cars;
for (int r : ranks) right = Math.min(right, (long) r * cars * cars);
while (left < right) {
long mid = left + (right - left) / 2;
if (canFinish(ranks, cars, mid)) right = mid;
else left = mid + 1;
}
return left;
}
private boolean canFinish(int[] ranks, int cars, long t) {
long repaired = 0;
for (int r : ranks) {
repaired += (long) Math.sqrt((double) t / r);
if (repaired >= cars) return true;
}
return false;
}
}func repairCars(ranks []int, cars int) int64 {
left, right := int64(1), int64(ranks[0])*int64(cars)*int64(cars)
for _, r := range ranks {
cand := int64(r) * int64(cars) * int64(cars)
if cand < right {
right = cand
}
}
for left < right {
mid := left + (right-left)/2
if canFinish(ranks, cars, mid) {
right = mid
} else {
left = mid + 1
}
}
return left
}
func canFinish(ranks []int, cars int, t int64) bool {
repaired := int64(0)
for _, r := range ranks {
repaired += int64(math.Sqrt(float64(t / int64(r))))
if repaired >= int64(cars) {
return true
}
}
return false
}class Solution {
public:
long long repairCars(vector<int>& ranks, int cars) {
long long left = 1, right = 1LL * *min_element(ranks.begin(), ranks.end()) * cars * cars;
while (left < right) {
long long mid = left + (right - left) / 2;
if (canFinish(ranks, cars, mid)) right = mid;
else left = mid + 1;
}
return left;
}
bool canFinish(vector<int>& ranks, int cars, long long t) {
long long repaired = 0;
for (int r : ranks) {
repaired += (long long) sqrt((long double)t / r);
if (repaired >= cars) return true;
}
return false;
}
};class Solution:
def repairCars(self, ranks: list[int], cars: int) -> int:
left, right = 1, min(ranks) * cars * cars
def can_finish(t: int) -> bool:
repaired = 0
for r in ranks:
repaired += int((t // r) ** 0.5)
if repaired >= cars:
return True
return False
while left < right:
mid = (left + right) // 2
if can_finish(mid):
right = mid
else:
left = mid + 1
return leftvar repairCars = function(ranks, cars) {
let left = 1n;
let minRank = BigInt(Math.min(...ranks));
let right = minRank * BigInt(cars) * BigInt(cars);
const canFinish = (t) => {
let repaired = 0n;
for (const r of ranks) {
repaired += BigInt(Math.floor(Math.sqrt(Number(t / BigInt(r)))));
if (repaired >= BigInt(cars)) return true;
}
return false;
};
while (left < right) {
const mid = left + (right - left) / 2n;
if (canFinish(mid)) right = mid;
else left = mid + 1n;
}
return Number(left);
};
Comments