【二分枚举答案】【数组】
2594. 修车的最少时间
给你一个表示机械工能力的数组 ranks
,ranks[i]
表示第 i
位机械工可以在 r a n k s [ i ] ∗ n 2 ranks[i] * n ^2 ranks[i]∗n2 分钟内修好 n
辆车。所有的机械工可以同时修理汽车,返回修理完所有汽车需要的最少时间。
如果已知修车的时间为 t t t,那么我们可以计算每个人在 t
分钟内可以修好的车辆数。如果一个工人的修车能力为 r
,则有这样的表达式:
r n 2 < = t rn^2 <= t rn2<=t
解得:
n < = t r n <= \sqrt{\frac{t}{r}} n<=rt
于是,能力值为 r
的工人最多可以修车 ⌊ t r ⌋ \lfloor{\frac{t}{r}}\rfloor ⌊rt⌋ 辆。
累加每个机械工在 t
分钟内的修车数量,如果有
∑ i = 0 n − 1 ⌊ t r a n k s [ i ] ⌋ > = c a r s \sum_{i=0}^{n-1}{\lfloor \sqrt{\frac{t}{ranks\left[ i \right]}} \rfloor}>=cars i=0∑n−1⌊ranks[i]t⌋>=cars
则说明可以在 t
分钟内修完所有的车。
上式表明,t
越大,能修好的车子越多。有了这样的单调性,我们就可以二分枚举答案了,二分的上界为修车最快的人修完所有车子的时间即 m i n ( r a n k s ) ⋅ c a r s 2 min(ranks) \cdot cars^2 min(ranks)⋅cars2。
在具体实现中,我们枚举修车的时间 t
,如果所有机械工在 t
分钟内修完的汽车数量大于等于 cars
,则调整右边界为 t
,否则调整左边界为 t+1
。
实现代码
class Solution {
public:
long long repairCars(vector<int>& ranks, int cars) {
int minR = *min_element(ranks.begin(), ranks.end());
long long left = 0, right = 1LL * minR * cars * cars;
auto check = [&](long long m) {
long long cnt = 0;
for (int r : ranks) {
cnt += sqrt(m / r);
}
return cnt >= cars;
};
while (left < right) {
long long mid = left + ((right - left) >> 1);
if (check(mid)) {
right = mid;
}
else {
left = mid + 1;
}
}
return left;
}
};
复杂度分析
时间复杂度: O ( n l o g L ) O(nlogL) O(nlogL), n n n 为数组 ranks
的长度, L L L 为二分的上界。
空间复杂度: O ( 1 ) O(1) O(1),因为仅用了常数个变量。
如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 。
如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。
最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 哦。