力扣每日一题:5764.准时到达的列车最小时速 Python二分
5764.准时到达的列车最小时速
难度:中等
题目:
给你一个浮点数 hour ,表示你到达办公室可用的总通勤时间。要到达办公室,你必须按给定次序乘坐 n 趟列车。另给你一个长度为 n 的整数数组 dist ,其中 dist[i] 表示第 i 趟列车的行驶距离(单位是千米)。
每趟列车均只能在整点发车,所以你可能需要在两趟列车之间等待一段时间。
例如,第 1 趟列车需要 1.5 小时,那你必须再等待 0.5 小时,搭乘在第 2 小时发车的第 2 趟列车。
返回能满足你准时到达办公室所要求全部列车的 最小正整数 时速(单位:千米每小时),如果无法准时到达,则返回 -1 。
生成的测试用例保证答案不超过 107 ,且 hour 的 小数点后最多存在两位数字 。
提示:
- n == dist.length
- 1 <= n <= 10**5
- 1 <= dist[i] <= 10 ** 5
- 1 <= hour <= 10 ** 9
- hours 中,小数点后最多存在两位数字
示例:
示例 1:
输入:dist = [1,3,2], hour = 6
输出:1
解释:速度为 1 时:
- 第 1 趟列车运行需要 1/1 = 1 小时。
- 由于是在整数时间到达,可以立即换乘在第 1 小时发车的列车。第 2 趟列车运行需要 3/1 = 3 小时。
- 由于是在整数时间到达,可以立即换乘在第 4 小时发车的列车。第 3 趟列车运行需要 2/1 = 2 小时。
- 你将会恰好在第 6 小时到达。
示例 2:
输入:dist = [1,3,2], hour = 2.7
输出:3
解释:速度为 3 时:
- 第 1 趟列车运行需要 1/3 = 0.33333 小时。
- 由于不是在整数时间到达,故需要等待至第 1 小时才能搭乘列车。第 2 趟列车运行需要 3/3 = 1 小时。
- 由于是在整数时间到达,可以立即换乘在第 2 小时发车的列车。第 3 趟列车运行需要 2/3 = 0.66667 小时。
- 你将会在第 2.66667 小时到达。
示例 3:
输入:dist = [1,3,2], hour = 1.9
输出:-1
解释:不可能准时到达,因为第 3 趟列车最早是在第 2 小时发车。
分析
这道题简直太符合每天卡点签到的我了,从7点55出门开始,一直优化到现在每天8点25风一般的卡点签到,哈哈。
这道题看到10**7,不用想就是二分,否则肯定超时!除了二分查找的时间优化,解题过程中有哪些优化点呢?
几点优化
-
客车每个整点发车
由于每趟列车乘坐的长度不同,需要我们对速度除以距离后取整。python整数相除取整公式一定要记住:
被除数 + 除数 - 1 // 除数
,只要整数多1,就可以保证向上取整了。 -
至少需要的小时数
由于列车整点出发,所以速度哪怕无穷大,前n-1车座列车最少也需要n-1个小时,
最后一次列车可以忽略到无穷小。那么hour 如何小于 len(dist) -1 则肯定无法抵达。 -
二分的最大值是多少?
二分查找需要设置最小值和最大值,然后进行二分操作,这道题的最大值该如何取,10**9吗?那你要多算多少次啊!
由于题目说了,hour小数最多存在两位,也就是最快0.01,那么右端点只需设置max(dist) * 100
就能满足题意。
这样会比 10 ** 9时间复杂度降低很多!
最后需要注意一点,hour的小数是怎么来的?因为前n-1次列车都是整点出发,所以小数是通过最后一趟列车来的!
下车后就认为到达终点了(地铁里打卡的骚操作?)。所以二分只循环计算前n-1,最后一次直接除保留小数。
理解了上面这些内容,这道题就变的很简单了,但Python的效率注定再怎么优化,耗时也渣的不行,尤其在大的数据量上更为明显。
来看看解题吧。
解题:
class Solution:
def minSpeedOnTime(self, dist, hour):
# 如果时间小于dist -1返回 -1
if hour < len(dist) - 1:
return -1
# 设置二分查找边界
left,right = 1, max(dist) * 100
while left < right:
cost, mid = 0, (left + right) // 2
for i in dist[:-1]:
cost += (i + mid - 1) // mid
# 如果cost已经大于hour,直接left移位,重新计算
if cost > hour:
left = mid + 1
continue
# 单独计算最后一次的耗时
cost += dist[-1] / mid
if cost > hour:
left = mid + 1
else:
right = mid
return -1 if left == 10 ** 9 else left
欢迎关注我的公众号: 清风Python,带你每日学习Python算法刷题的同时,了解更多python小知识。
我的个人博客:https://qingfengpython.cn