文章目录
- Tag
- 题目来源
- 题目解读
- 解题思路
- 方法一:二分枚举答案
- 写在最后
Tag
【二分枚举答案】【数组】
题目来源
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),因为仅用了常数个变量。
写在最后
如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。
如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。
最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。