LeetCode - 1870, Minimum Speed to Arrive on Time
LeetCode 1870 solution explanation
Challenge Description
You are given a floating-point number hour, representing the amount of time you have to reach the office. To commute to the office, you must take n trains in sequential order. You are also given an integer array dist of length n, where dist[i]
describes the distance (in kilometers) of the $i^{\text{th}}$ train ride.
Each train can only depart at an integer hour, so you may need to wait in between each train ride.
- For example, if the 1st train ride takes $1.5$ hours, you must wait for an additional 0.5 hours before you can depart on the 2nd train ride at the 2 hour mark.
Return the minimum positive integer speed (in kilometers per hour) that all the trains must travel at for you to reach the office on time, or $-1$ if it is impossible to be on time.
Tests are generated such that the answer will not exceed $10^7$ and hour will have at most two digits after the decimal point.
Example 1:
Input: dist = [1,3,2]
, hour = 6
Output: 1
Explanation: At speed 1:
- The first train ride takes 1/1 = 1 hour.
- Since we are already at an integer hour, we depart immediately at the 1 hour mark. The second train takes 3/1 = 3 hours.
- Since we are already at an integer hour, we depart immediately at the 4 hour mark. The third train takes 2/1 = 2 hours.
- You will arrive at exactly the 6 hour mark.
Reformulating the problem
Let’s begin by reformulating the problem to make it easier to develop a solution algorithm.
Given the problem, if we are at an exact integer hour, we can depart immediately. In this case, the time taken for the $i^{\text{th}}$ train ride is:
$$ \begin{aligned} \frac{\text{dist}[i]}{x} \end{aligned} $$
where $x$ is the speed value we need to determine. If we arrive at a non-integer hour, we must wait until the next full hour before we can depart. Therefore, the effective time spent includes this waiting period, which can be represented as:
$$ \begin{aligned} \frac{\text{dist}[i]}{x} + \left\lceil \frac{\text{dist}[i]}{x} \right\rceil - \frac{\text{dist}[i]}{x} \end{aligned} $$
For the last train ride, there is no need to wait, so the time taken is simply:
$$ \begin{aligned} \frac{\text{dist}[i]}{x} \end{aligned} $$
Our objective is to find the minimum speed $x$ such that the total time spent on all train rides is less than or equal to the given hour. This can be expressed mathematically as:
$$ \begin{aligned} \sum_{i=1}^{n-1} \left\lceil \frac{\text{dist}[i]}{x} \right\rceil + \frac{\text{dist}[n]}{x} \leq \text{hour} \end{aligned} $$
Given that this is a non-linear function involving a ceiling operation, binary search is a suitable and efficient method to find the minimum value of x that satisfies this condition.
Binary search code
We implement a binary search algorithm in a C++
code:
class Solution {
public:
bool canReachInTime(const vector<int> &dist, double hour, int speed)
{
double time = 0;
for (size_t i = 0; i < dist.size() - 1; ++i)
time += ceil(static_cast<double>(dist[i]) / speed);
time += static_cast<double>(dist.back()) / speed;
return time <= hour;
}
int minSpeedOnTime(const vector<int> &dist, double hour)
{
int low = 1, high = 1e7;
while (low < high)
{
int mid = low + (high - low) / 2;
if (canReachInTime(dist, hour, mid))
high = mid;
else
low = mid + 1;
}
return canReachInTime(dist, hour, low) ? low : -1;
}
};
And then our submission will get all the tests validated.