前言
本人前端算法小白,喜欢闲暇之余刷刷 LeetCode,上周参与 2.27 第 282 场周赛败在第三题,T3 超时了 =-=,所以也没有摸到 T4,所以痛定思痛打算好好研究一下 T3,有兴趣也可以一起研究。
一、题目描述
给你一个数组 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 <= 105
- 1 <= time[i], totalTrips <= 107
二、题目分析
-
找到完成 至少 totalTrips 趟旅途需要花费的 最少时间,可以使用二分查找降低时间复杂度
-
首先可以找到完成一趟旅途所需要花费的时间的最少时间 min 作为二分查找的左边界 left
-
然后可以通过计算 totalTrips * min 获得旅途花费的最多时间 作为二分查找的右边界 right
-
计算中间时间 middle 以及 在 middle 内能完成得旅途数目 trips
-
如果 trips 大于 totalTrips,表明仍然存在更小的时间来完成旅途,所以继续向左查找
-
如果 trips 小于 totalTrips,表明 middle 内不足以完成约定的旅途,继续向右查找
-
最终找到复合条件的时间
三、代码实现
/**
* @param {number[]} time
* @param {number} totalTrips
* @return {number}
*/
var minimumTime = function (time, totalTrips) {
// 找到最小值 left
let left = Math.min(...time);
// 找到最大值 right 也就是最小值 min * totalTrips
let right = totalTrips * left;
// 使用二分查找筛选符合的条件
while (left < right) {
let middle = left + Math.floor((right - left) /2);
let trips = 0;
// 遍历每个车次需要完成的时间
for (const t of time) {
// 计算可以完成的旅途数
trips += Math.floor(middle / t);
if (trips >= totalTrips) break;
}
// 如果超过 totalTrips,缩小到前半部分继续向左查找,反之缩小到后半部分向右查找
if (trips >= totalTrips) {
right = middle;
} else {
left = middle + 1;
}
}
return left;
};
四、相似题目
二分查找类型:感兴趣的也可以自己去研究研究
写在最后
仍在努力学习算法,也在解题中获得很多乐趣,也许现在周赛只能完成一题、两题,但是我还是会继续坚持下去的。
今年目标:leetCodeNum += 200;
加油!