写在前面的话
欢迎扫码关注我的公众号,与我一同学习进步!主要致力于学习
- 使用深度学习解决计算机视觉相关问题
- Python为主的互联网应用服务
- 基于MIPS指令集的CPU微体系结构设计
题目描述
1011. 在 D 天内送达包裹的能力
问题分析
从二分法谈起
二分法的核心是找到合适的解空间,之后在这个解空间中进行二分搜索,直至找到合适的解(满足题目要求的)。
在该问题中,我们需要找到合适的载重量,以便在规定的时间内完成货物运载,因此求解的问题就是找到合适的载重量,载重量就是我们需要求解的内容。
确定解空间
在该问题中,船舶的载重量是根据天数确定的。因此,天数最少为1天,最多可为任意天。根据此,当天数为1天时,船舶的载重量取到最大值,为所有重物的重量和;当天数为任意天时,船舶的载重量取到最小值,为1。
但是,该问题给出了其他限制条件,如下图所示。即天数不大于重物的数量,那么,需要相应的修改船舶的载重量的最小值为货物中最大的重量。原因在于:每次必须至少运送一个货物,才可以确保所有的货物可以在D天内运送完成。
综上所述,即可确保船舶的载重量的解空间为**[所有货物中最大的载重值,所有货物的载重值得综合]**
二分搜索——改变解空间
由于解空间已经确定,可使用如下的二分法通用模板进行二分搜索,以不断地改变解空间,直到寻找到合适的解。
"""
@param
left: 左区间,可以取到的最小值
right: 右区间,可以取到的最大值
"""
while left < right:
medium = left + (right - left) // 2
if 右条件满足:
更新左边界
elif 左条件满足:
更新右边界
return 结果
针对该问题,我们需要对每个载重量的取值带入进行运算,求解在船舶承载该重量的情况下,运送完所有的货物需要的时间。针对计算结果,我们进行如下的改变区间的方法:
- 当所需时间小于给定时间时,说明在船舶承载该重量的情况下,可以完成运输任务,但此时的载重量并不是题目要求的求解的最低载重量,我们需要更新右边界的取值
- 当所需时间大于给定时间时,说明在船舶承载该重量的情况下,无法完成运输任务,需要增大船舶的载重量,我们需要更新左边界的值
由于给定的方法为Solution类,我们需要额外写一个函数来实现该功能,以简写程序
代码编写
针对以上的问题分析,转变为代码语言,可写为如下的形式
class Solution:
def shipWithinDays(self, weights: List[int], D: int) -> int:
# 初始化解空间的左、右边界
left = max(weights)
right = sum(weights)
# 更新解空间,寻找最优值
while left < right:
medium = left + (right - left) // 2
# 满足左条件
if self.days(weights, medium) > D:
left = medium + 1
# 满足右条件
else:
right = medium
# 返回结果
return left
# 计算花费的时间,根据结果更新解空间的左、右边界
def days(self, weights: List[int], weight: int) -> int:
# 这里需要注意,将天数设置为1,因为至少需要1天才能运送完所有的货物
day = 1
cur = 0
for item in weights:
if (cur + item) > weight:
day += 1
cur = 0
cur += item
return day
同类题目
题目描述
875. 爱吃香蕉的珂珂
差异分析
与上一题相比,它的主要区别体现在两个地方
- 对于无序数组中的值处理的方法不同,上一题的值指的是货物的重量,该题的值指的是香蕉的数量,且该题每一个单位时间至多只能处理数组中的一个值
- 它对于数组中的值与小时数之间没有要求,初始化的解空间发生了改变
- 它的计时需要从第0个小时开始计算,原因在于只要数组不为空,那么就至少需要有一个小时来吃香蕉
代码编写
以下附上求解本题的完成代码
class Solution:
def minEatingSpeed(self, piles: List[int], h: int) -> int:
left = 1
# H一定大于数组的长度,要不然是吃不完的
# 那么,它的极大取值就是数组中最大的值
right = max(piles)
while left < right:
medium = left + (right - left) // 2
# print(left, right)
if self.hours(piles, medium) > h:
left = medium + 1
else:
right = medium
return left
def hours(self, piles: List[int], k: int) -> int:
hour = 0
cur = 0
for item in piles:
if item < k:
hour += 1
else:
tmp = item % k
if tmp != 0:
hour = hour + item // k + 1
else:
hour = hour + item // k
# print(hour)
return hour