二分查找
算法思路:题目要求解修理汽车所需的最少时间,故先考虑二分是否可行,若解的值域范围内有单调性,就可以使用二分:
- 假设 t t t 分钟内可以将所有骑车都修理完,那么大于等于 t t t 分钟内都可以将所有汽车修理完。
- 假设 t t t 分钟内不能将所有骑车都修理完,那么小于等于 t t t 分钟内都不能将所有汽车修理完。
因此,解的值域范围存在单调性。我们枚举一个时间 t t t,那么能力值为 x x x 的工人可以修完 ⌊ t x ⌋ \lfloor\sqrt{\frac{t}{x}}\rfloor ⌊xt⌋ 辆汽车。若所有工人可以修完的汽车数量之和大于等于 c a r s cars cars,那么调整右边界为 t t t,否则调整左边界为 t + 1 t+1 t+1。
二分的上界可以取正无穷,也可以取任意一个工人修完所有车辆所需要的时间。
代码:
class Solution {
public:
long long repairCars(vector<int>& ranks, int cars) {
long long left = 1, right = 1ll * ranks[0] * cars * cars;//left初始化最短时间1分钟,right初始化最长时间由ranks[0]全部完成
auto check = [&](ll m){ //判断m分钟内所有工人修完的汽车数是否满足要求的数量
long long cnt = 0;
for(auto x : ranks){ //计算m分钟内所有工人可以维修多少辆车
cnt += sqrt(m / x);
}
return cnt >= cars;
};
while(left < right){ //二分查找
long long m = left + right >> 1;
if(check(m)){ //如果m分钟内能完成,则缩小上限,寻找最短时间
right = m;
}else{ //如果m分钟内无法完成,则增加下限,二分查找
left = m + 1;
}
}
return left;
}
};
复杂度分析:
- 时间复杂度: O ( n log L ) O(n\log{L}) O(nlogL),其中 n n n 为 r a n k s ranks ranks 的长度, L L L 为二分的上界。
- 空间复杂度: O ( 1 ) O(1) O(1)