
问题解析力扣1011 题 “在 D 天内送达包裹的能力” 要求确定在给定天数D内将所有包裹从传送带上运完的最低运载能力。运载能力capacity表示船每天能运送的最大重量且必须按数组顺序运送每天运送的总重量不能超过capacity。核心思路这是一个二分查找问题。运载能力capacity存在一个可行域下界left至少需要能运走最重的单个包裹即max(weights)。上界right最坏情况一天运完所有包裹即sum(weights)。在[left, right]范围内对于任意一个capacity我们可以通过模拟运送过程计算出所需天数needDays。根据needDays与D的关系来调整二分查找的边界*若needDays D说明当前运力充足或刚好可以尝试减小运力缩小右边界。若needDays D说明当前运力不足必须增大运力增大左边界。最终left即为所求的最小运力。C 代码实现class Solution { public: int shipWithinDays(vectorint weights, int D) { // 确定二分查找的左右边界 int left *max_element(weights.begin(), weights.end()); // 运力至少能装下最重的包裹 int right accumulate(weights.begin(), weights.end(), 0); // 运力最多一天运完所有 while (left right) { int mid left (right - left) / 2; // 当前尝试的运力 int need 1; // 需要运送的天数初始为1天 int cur 0; // 当前这一天已经装载的重量 // 模拟以 mid 为运力运送所有包裹所需的天数 for (int weight : weights) { if (cur weight mid) { // 如果加上当前包裹会超载 need; // 则需要新的一天 cur weight; // 新的一天从当前包裹开始装 } else { cur weight; // 没超载继续装 } } // 根据所需天数调整二分边界 if (need D) { right mid; // 运力足够或有余尝试更小的运力 } else { left mid 1; // 运力不足必须增大 } } return left; // 此时 left right即为最小运力 } };代码说明边界初始化left初始化为数组最大值right初始化为数组总和 。二分查找循环当left right时计算中间值mid作为尝试的运力。模拟运送函数内嵌循环遍历所有包裹累加当前天的重量cur。若加上当前包裹后重量超过mid则天数need加一并在新的一天开始运送该包裹 。边界调整若计算出的所需天数need小于等于D说明运力mid可行为了寻找最小运力将搜索范围缩小至左半部分 (right mid)。若need大于D说明运力mid不足需增大运力将搜索范围调整至右半部分 (left mid 1)。返回值循环结束时left和right相等即为满足条件的最小运力。复杂度分析时间复杂度O(n log m)其中n是包裹数量m是包裹总重量。二分查找复杂度为 O(log m)每次模拟运送需要 O(n)。空间复杂度O(1)只使用了常数个额外变量。示例输入weights [1,2,3,4,5,6,7,8,9,10],D 5left 10,right 55。第一次尝试mid (1055)/2 32模拟运送[1,2,3,4,5,6,7,8](3632分两天)[9,10]共需3天 (need3)。3 5所以right 32。继续二分最终找到最小运力为15。验证以运力15运送[1,2,3,4,5],[6,7],[8],[9],[10]正好需要5天。参考来源LeetCode1011❤️67❤️带新手一起刷力扣 (LeetCode)❤️代码有详细的注释❤️反思总结❤️67. 二进制求和力扣67-二进制求和-CLeetcode 693. 交替位二进制数 CLeetcode 67. 二进制求和 C