import math
class Solution:
def minSpeedOnTime(self, dist, hour):
left, right = 1, 10**7
n = len(dist)
res = -1
while left <= right:
mid = (left + right) // 2
time = 0.0
for i in range(n - 1):
time += math.ceil(dist[i] / mid)
time += dist[-1] / mid
if time <= hour:
res = mid
right = mid - 1
else:
left = mid + 1
return res
#include <vector>
#include <cmath>
using namespace std;
class Solution {
public:
int minSpeedOnTime(vector<int>& dist, double hour) {
int left = 1, right = 1e7, res = -1, n = dist.size();
while (left <= right) {
int mid = left + (right - left) / 2;
double time = 0.0;
for (int i = 0; i < n - 1; ++i)
time += ceil((double)dist[i] / mid);
time += (double)dist[n-1] / mid;
if (time <= hour) {
res = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return res;
}
};
class Solution {
public int minSpeedOnTime(int[] dist, double hour) {
int left = 1, right = 10000000, res = -1, n = dist.length;
while (left <= right) {
int mid = left + (right - left) / 2;
double time = 0.0;
for (int i = 0; i < n - 1; ++i)
time += Math.ceil((double)dist[i] / mid);
time += (double)dist[n-1] / mid;
if (time <= hour) {
res = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return res;
}
}
/**
* @param {number[]} dist
* @param {number} hour
* @return {number}
*/
var minSpeedOnTime = function(dist, hour) {
let left = 1, right = 1e7, res = -1, n = dist.length;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
let time = 0.0;
for (let i = 0; i < n - 1; ++i)
time += Math.ceil(dist[i] / mid);
time += dist[n-1] / mid;
if (time <= hour) {
res = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return res;
};
You are given an array dist
where dist[i]
represents the distance of the i-th train ride, and a floating-point number hour
representing the total time you have to arrive at your destination. You must take the train rides in order, and after each ride (except the last), you must wait until the next integer hour to depart (i.e., you can only depart at whole hours).
Your task is to find the minimum integer speed (in units per hour) such that you can complete all the rides within hour
hours. If it is impossible to arrive on time, return -1
.
At first glance, we might consider simulating all possible speeds, checking for each if we can arrive on time. However, with the constraints (distances can be up to 105 and the answer can be as high as 107), brute-force is computationally expensive.
The main challenge comes from the "wait until the next integer hour" rule for each ride except the last. This means that for every ride except the last, we must round up the time spent to the next integer. This rounding introduces complexity in calculating the total travel time.
Since the answer must be the minimum integer speed that works, and the function mapping speed to travel time is monotonic (higher speed never increases travel time), we can use binary search to efficiently find the answer.
ceil(dist[i] / speed)
(since you must wait for the next integer hour).dist[last] / speed
.hour
, try a lower speed (move the right boundary).ceil
) where required.-1
if no speed in the range works.
Input: dist = [1, 3, 2]
, hour = 6
ceil(1/1) = 1
hourceil(3/1) = 3
hours2/1 = 2
hourshour
exactly, so speed = 1 works.hour = 2.7
:ceil(1/3) = 1
hourceil(3/3) = 1
hour2/3 ≈ 0.666...
hourThe binary search will efficiently find the minimum such speed.
The key insight is to realize that the total time function is monotonic with respect to speed, enabling a binary search for the minimum speed. By carefully simulating the waiting rule (using ceiling for all but the last ride), we can efficiently determine the answer. This approach is both elegant and efficient, leveraging properties of monotonic functions and binary search to solve what would otherwise be an intractable problem.