Medium
题目描述
给你一个数组 time ,其中 time[i] 表示第 i 辆公共汽车完成一趟旅途所需要花费的时间。
每辆公共汽车可以 连续 完成多趟旅途,也就是说,一辆公共汽车当前旅途结束后,可以 立即 开始下一趟旅途。每辆公共汽车 独立 运行,也就是说可以同时有多辆公共汽车在运行且互不影响。
给你一个整数 totalTrips ,表示所有公共汽车 总共 需要完成的旅途数目。请返回完成 至少 totalTrips 趟旅途需要花费的 最少 时间。
示例 1:
输入:time = [1,2,3], totalTrips = 5
输出:3
解释:
- 时刻 t = 1 ,每辆公共汽车完成的旅途数分别为 [1,0,0] 。
已完成的总旅途数为 1 + 0 + 0 = 1 。
- 时刻 t = 2 ,每辆公共汽车完成的旅途数分别为 [2,1,0] 。
已完成的总旅途数为 2 + 1 + 0 = 3 。
- 时刻 t = 3 ,每辆公共汽车完成的旅途数分别为 [3,1,1] 。
已完成的总旅途数为 3 + 1 + 1 = 5 。
所以完成至少 5 趟旅途的最少时间为 3 。
示例 2:
输入:time = [2], totalTrips = 1
输出:2
解释:
只有一辆公共汽车,它将在时刻 t = 2 完成第一趟旅途。
所以完成 1 趟旅途的最少时间为 2 。
提示:
1 <= time.length <= 10^51 <= time[i], totalTrips <= 10^7
解题思路
这是一道经典的二分搜索问题。核心思想是利用时间的单调性:给定的时间越长,完成的旅途数越多。
分析过程:
问题转化:我们需要找到最小的时间
t,使得在时间t内所有公交车能完成至少totalTrips趟旅途。关键观察:对于给定时间
t,第i辆公交车能完成的旅途数为⌊t / time[i]⌋。所有公交车的总旅途数为所有公交车各自完成旅途数的和。二分搜索范围:
- 下界:1(至少需要1个时间单位)
- 上界:
min(time) * totalTrips(最快的公交车完成所有旅途所需时间)
判断条件:给定时间
mid,计算所有公交车能完成的总旅途数,如果≥ totalTrips,说明时间充足,可以尝试更小的时间;否则需要更多时间。
算法步骤:
- 设置二分搜索的左右边界
- 在每次迭代中,计算中间时间点所有公交车能完成的总旅途数
- 根据是否满足条件调整搜索范围
- 返回满足条件的最小时间
时间复杂度为 O(n log(min(time) × totalTrips)),空间复杂度为 O(1)。
代码实现
class Solution {
public:
long long minimumTime(vector<int>& time, int totalTrips) {
long long left = 1;
long long right = (long long)*min_element(time.begin(), time.end()) * totalTrips;
while (left < right) {
long long mid = left + (right - left) / 2;
long long trips = 0;
for (int t : time) {
trips += mid / t;
}
if (trips >= totalTrips) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
};
class Solution:
def minimumTime(self, time: List[int], totalTrips: int) -> int:
left, right = 1, min(time) * totalTrips
while left < right:
mid = (left + right) // 2
trips = sum(mid // t for t in time)
if trips >= totalTrips:
right = mid
else:
left = mid + 1
return left
public class Solution {
public long MinimumTime(int[] time, int totalTrips) {
long left = 1;
long right = (long)time.Min() * totalTrips;
while (left < right) {
long mid = left + (right - left) / 2;
long trips = 0;
foreach (int t in time) {
trips += mid / t;
}
if (trips >= totalTrips) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}
/**
* @param {number[]} time
* @param {number} totalTrips
* @return {number}
*/
var minimumTime = function(time, totalTrips) {
let left = 1;
let right = Math.min(...time) * totalTrips;
while (left < right) {
const mid = Math.floor((left + right) / 2);
let trips = 0;
for (const t of time) {
trips += Math.floor(mid / t);
}
if (trips >= totalTrips) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
};
复杂度分析
| 复杂度类型 | 复杂度 |
|---|---|
| 时间复杂度 | O(n × log(min(time) × totalTrips)) |
| 空间复杂度 | O(1) |
其中 n 是公交车的数量,二分搜索的范围是 [1, min(time) × totalTrips],每次检查需要遍历所有公交车。