问题思路
题目要求我们在限定的天数内,通过合理分配每天的运输量,确保所有包裹都能被运送到目的地。这个问题可以转化为一个典型的背包问题,其中我们需要在给定的天数(背包容量)内,运输尽可能多的包裹(物品),同时不超过每天的运输能力(背包容量限制)。
我们可以采用二分查找来解决此问题。因为运载能力的取值范围是有边界的,下限是weights中的最大值(若运载能力小于此值,最大的包裹无法运输),上限是weights的总和(若运载能力等于总和,可一天运完所有包裹)。在二分查找过程中,对于每次尝试的运载能力mid,计算按此运载能力运输所有包裹需要的天数cur_days。若cur_days小于等于days,说明运载能力可能过大,应缩小上限;若cur_days大于days,说明运载能力过小,应增大下限。
问题详解
这是一个典型的二分查找问题,我们需要找到一个最小的运载能力值,使得在这个能力下,所有包裹能在限定的天数内被运送。
首先确定二分查找的上下界:上界是所有包裹重量之和(即总重量),下界是包裹中的最大单个重量。
接着编写辅助函数:创建一个函数can_ship_in_days(capacity)来判断在给定的运载能力下,是否可以在规定的天数内完成运输。
最后二分查找逻辑:通过不断调整中间值mid,根据can_ship_in_days(mid)的返回结果来调整上下界,直到找到最小的运载能力。
代码
def solution(weights: list, days: int) -> int:
# 辅助函数:检查给定的运载能力是否能在 days 天内完成运输
def can_ship_in_days(capacity: int) -> bool:
# 初始化当前天数和当前载重
current_days = 1
current_load = 0
for weight in weights:
# 如果当前载重加上当前包裹的重量超过 capacity,则需要新的一天
if current_load + weight > capacity:
current_days += 1
current_load = weight
else:
current_load += weight
# 返回是否能在 days 天内完成运输
return current_days <= days
# 二分查找的左右边界
left, right = max(weights), sum(weights)
# 二分查找
while left < right:
mid = (left + right) // 2
if can_ship_in_days(mid):
right = mid
else:
left = mid + 1
return left
if name == 'main':
print(solution(weights=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1], days=5) == 15)
print(solution(weights=[3, 2, 2, 5, 1, 4], days=2) == 10)
print(solution(weights=[1, 2, 3, 8, 4], days=4) == 8)
代码详解
1.函数定义与辅助函数
def solution(weights: list, days: int) -> int:定义了主函数,接受包裹重量列表和天数作为参数,并返回最低运载能力。
def can_ship_in_days(capacity: int) -> bool:是辅助函数,用于检查给定的运载能力是否能在days天内完成运输。在这个函数中:
初始化current_days = 1和current_load = 0,分别表示当前天数和当前载重。
遍历weights列表,对于每个包裹重量weight,如果current_load + weight > capacity,则需要新的一天,current_days加 1,current_load重置为weight;否则,current_load加上weight。
最后返回current_days <= days,判断是否能在规定天数内完成运输。
2.二分查找实现
left, right = max(weights), sum(weights)初始化了二分查找的左右边界。
在while left < right:循环中:
mid = (left + right) // 2计算中间运载能力。
通过if can_ship_in_days(mid):判断以mid为运载能力是否能在days天内完成运输。若可以,right = mid缩小上限;否则,left = mid + 1增大下限。
最后返回left,即最低运载能力。
3.主程序测试
在if name == 'main':部分,对solution函数进行了测试,分别传入了题目中给出的三组测试数据,验证函数返回值是否正确。
知识总结
在使用豆包MarsCode AI刷题过程中,我学到了以下几个新知识点:
二分查找的应用场景:二分查找不仅仅适用于有序数组的查找,还可以用来解决很多优化类问题,比如寻找最优解或者阈值等问题。
辅助函数的重要性:在处理复杂的逻辑时,引入辅助函数不仅可以使主函数更加简洁易懂,还能方便地复用这些逻辑。
边界条件的处理:在编写算法时,一定要注意边界条件的处理,避免出现错误的结果。
多做练习:只有通过大量的实践才能真正掌握一门技术。
学会总结:每次做完一道题之后,都要花时间去回顾和总结,看看有没有什么可以改进的地方。
利用好工具:像豆包MarsCode这样的工具可以帮助我们更好地管理学习进度,提升效率。
工具运用
豆包MarsCode AI刷题功能提供了丰富的题目资源和智能化的指导,可以帮助用户更高效地学习。结合其他学习资源,如在线教程、视频讲解等,可以进一步丰富学习体验,提高学习效果。