leetcode
leetcode 1651 ~ 1700
准时到达的列车最小时速

准时到达的列车最小时速

难度:

标签:

题目描述

代码结果

运行时间: 624 ms, 内存: 27.5 MB


/*
 * 思路:
 * 我们需要找到一个最小的正整数速度,使得总通勤时间不超过给定的小时数。如果找不到这样的速度,就返回-1。
 * 我们可以使用二分查找来找到这个最小的速度。
 * 首先,我们设定速度的下界为1,上界为10^7。
 * 然后我们计算每个速度下需要的总通勤时间,并通过比较总时间和给定时间来调整速度的上下界。
 * 使用Java Stream实现总时间计算。
 */
import java.util.stream.IntStream;

public class Solution {
    public int minSpeedOnTime(int[] dist, double hour) {
        int left = 1, right = 10000000;
        int result = -1;
        while (left <= right) {
            int mid = left + (left + right) / 2;
            if (canReachOnTime(dist, hour, mid)) {
                result = mid;
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return result;
    }

    private boolean canReachOnTime(int[] dist, double hour, int speed) {
        double totalTime = IntStream.range(0, dist.length)
            .mapToDouble(i -> i == dist.length - 1 ? (double) dist[i] / speed : Math.ceil((double) dist[i] / speed))
            .sum();
        return totalTime <= hour;
    }
}

解释

方法:

这个题解使用了二分查找的方法来寻找最小的满足条件的时速。首先,如果可用时间小于列车数量减一(即hour <= n - 1),则无法准时到达,返回-1。接着,定义搜索区间的左右边界,左边界设为0(不可能的速度),右边界设为max(dist)和ceil(dist[-1] / (hour - (n - 1)))的较大值,保证这个速度一定能到达。然后,进行二分查找,计算中间值mid,检查以mid为速度是否能准时到达。如果能,说明速度还可以更小,移动右边界;如果不能,说明速度需要增加,移动左边界。最终返回右边界作为结果。

时间复杂度:

O(nlog(maxSpeed))

空间复杂度:

O(1)

代码细节讲解

🦆
在二分查找中,为什么左边界设定为0而不是1,考虑到速度为0是不可能的情况?
在二分查找中,设置左边界为0虽然0速度不现实,这样做主要是为了简化边界处理。具体到算法实现中,我们并不会真正考虑速度为0的情况,因为在二分查找过程中,实际计算始终从中间值开始,即`mid = (left + right) // 2`,而当左边界为0时,第一个mid一定大于0(只要right初始值大于0)。这种设置简化了代码,避免了对速度为1的特殊处理。
🦆
你为什么选择将右边界设为max(dist)和ceil(dist[-1] / (hour - (n - 1)))的较大值,可以详细解释这个计算的逻辑吗?
右边界的设定是为了确保所选速度一定能覆盖最极端的情况。考虑两种情况:1) max(dist)确保速度足以在一个单位时间内通过任何单一段的最大距离。2) `ceil(dist[-1] / (hour - (n - 1)))`确保最后一段可以在剩余时间内走完。这个时间是总时间减去前面n-1段至少需要的时间(每段至少需要1小时,不考虑速度)。选择这两者的较大值作为右边界,是为了保证在所有情况下,选择的速度都能满足题目要求,从而使算法的正确性和全面性得到保证。
🦆
为什么在二分查找的循环条件中使用`left + 1 < right`而不是`left < right`?这样的终止条件有什么特别的考虑吗?
使用`left + 1 < right`作为循环终止条件是为了避免在循环体内出现死循环,并精确控制搜索范围。当两个边界相邻时(left和right之间的差为1),如果继续使用`left < right`作为条件,有可能导致mid重复计算同一个值,从而陷入无限循环。使用`left + 1 < right`确保了当两个边界相邻时退出循环,这时right指向的值是满足条件的最小速度,这样可以有效地找到解决方案。
🦆
在二分查找中,如果mid速度刚好使得`need == hour`,为什么还需要尝试更小的速度?
即使`need == hour`表明当前速度mid可以准时到达,算法仍需尝试更小的速度,以确保找到‘最小’的满足条件的速度。这是因为题目要求的是‘最小’时速。如果不继续尝试更小的速度,就可能错过更优的解。因此,即使当前mid满足条件,也将右边界移动到mid,继续搜索左半区间,以便探索是否有更小的可行速度。

相关问题