二分法在无序数组中的应用

本文探讨了如何使用深度学习处理计算机视觉问题,特别是在解决货物运输的优化策略中,通过二分法寻找在限定时间内完成包裹送达的最小载重量。文章详细阐述了二分法的应用,包括确定解空间、实施二分搜索以及更新边界条件。此外,还对比了类似问题在不同场景下的应用,例如在香蕉食用速度问题上的差异。
摘要由CSDN通过智能技术生成

写在前面的话

欢迎扫码关注我的公众号,与我一同学习进步!主要致力于学习

  1. 使用深度学习解决计算机视觉相关问题
  2. Python为主的互联网应用服务
  3. 基于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. 爱吃香蕉的珂珂

在这里插入图片描述

差异分析

与上一题相比,它的主要区别体现在两个地方

  1. 对于无序数组中的值处理的方法不同,上一题的值指的是货物的重量,该题的值指的是香蕉的数量,且该题每一个单位时间至多只能处理数组中的一个值
  2. 它对于数组中的值与小时数之间没有要求,初始化的解空间发生了改变
  3. 它的计时需要从第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
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值