二分算法02

二分算法02

  • [1. 每个小孩最多能分到多少糖果](#1. 每个小孩最多能分到多少糖果)
  • [2. 准时到达的列车最小时速](#2. 准时到达的列车最小时速)
  • [3. 在 D 天内送达包裹的能力](#3. 在 D 天内送达包裹的能力)

1. 每个小孩最多能分到多少糖果

给你一个 下标从 0 开始 的整数数组 candies 。数组中的每个元素表示大小为 candies[i] 的一堆糖果。你可以将每堆糖果分成任意数量的 子堆 ,但 无法 再将两堆合并到一起。

另给你一个整数 k 。你需要将这些糖果分配给 k 个小孩,使每个小孩分到 相同 数量的糖果。每个小孩可以拿走 至多一堆 糖果,有些糖果可能会不被分配。

返回每个小孩可以拿走的 最大糖果数目 。

真题点击此处:2226. 每个小孩最多能分到多少糖果

解题思路:

假设有一个长度为 n 的数组 candies,表示每个糖果的数量。现在我们希望将这些糖果平均分配给 k 个孩子。我们需要找到一个最大的正整数 x,使得将每个糖果分成 x 份后,每个孩子都可以得到至少一份,并且可以得到最大总糖果数。

  1. 我们首先定义两个指针 left 和 right,分别指向可能的最小值 1 和最大值 max(candies)。
  2. 然后我们使用二分查找的方法,不断缩小 left 和 right 的范围,直到 left > right 为止。
  3. 在每次循环中,我们计算 mid = (left + right) // 2,表示当前的糖果份数。
  4. 接着,我们遍历数组 candies,计算出将每个糖果分成 mid 份后,可以得到的总糖果数 ans。
  5. 如果 ans < k,说明当前的份数过多,我们需要将 right 指针左移,将搜索范围从右半部分继续缩小。
  6. 如果 ans >= k,说明当前份数过少或刚好符合要求,我们需要将 left 指针右移,将搜索范围从左半部分继续缩小。
  7. 最终返回 left - 1,即为最大的正整数 x。

具体解题思路可以总结为以下几点:

  • 定义两个指针 left 和 right,分别指向可能的最小值 1 和最大值 max(candies)。
  • 使用二分查找的方法,不断缩小 left 和 right 的范围,直到 left > right 为止。
  • 在每次循环中,计算 mid = (left + right) // 2,表示当前的糖果份数。
  • 遍历数组 candies,计算出将每个糖果分成 mid 份后,可以得到的总糖果数 ans。
  • 如果 ans < k,将 right 指针左移,将搜索范围从右半部分继续缩小。
  • 如果 ans >= k,将 left 指针右移,将搜索范围从左半部分继续缩小。
  • 最终返回 left - 1,即为最大的正整数 x。

这种方法利用了二分查找的特性,不断缩小搜索范围,最终得到符合要求的最大的正整数 x。

以下为代码实现:

python 复制代码
class Solution:
    def maximumCandies(self, candies: List[int], k: int) -> int:
        left, right = 1, max(candies)

        while left <= right:
            mid = (left + right) // 2
            ans = 0
            for c in candies:
                ans += c // mid
            if ans < k:
                right = mid - 1
            else:
                left = mid + 1

        return left - 1

时间复杂度:O(nlogm),其中 n 为糖果数组 candies 的长度,m 为糖果数组中最大的数值。

空间复杂度:O(1),该算法只使用了常数级别的额外空间用于存储变量。

2. 准时到达的列车最小时速

给你一个浮点数 hour ,表示你到达办公室可用的总通勤时间。要到达办公室,你必须按给定次序乘坐 n 趟列车。另给你一个长度为 n 的整数数组 dist ,其中 dist[i] 表示第 i 趟列车的行驶距离(单位是千米)。

每趟列车均只能在整点发车,所以你可能需要在两趟列车之间等待一段时间。

例如,第 1 趟列车需要 1.5 小时,那你必须再等待 0.5 小时,搭乘在第 2 小时发车的第 2 趟列车。

返回能满足你准时到达办公室所要求全部列车的 最小正整数 时速(单位:千米每小时),如果无法准时到达,则返回 -1 。

生成的测试用例保证答案不超过 107 ,且 hour 的 小数点后最多存在两位数字 。

真题点击此处:1870. 准时到达的列车最小时速

解题思路:

假设有一个长度为 n 的数组 dist,表示一系列区间的距离,以及一个代表旅行所需总时间的浮点数 hour。现在我们需要找到一个最小的速度 x,使得以这个速度行驶的话,可以在规定时间内完成旅程。

  1. 首先定义两个指针 left 和 right,分别指向可能的最小速度 1 和最大速度 10^7。
  2. 使用二分查找的方法,不断缩小 left 和 right 的范围,直到 left > right 为止。
  3. 在每次循环中,计算 mid = (left + right) // 2,表示当前的速度。
  4. 遍历数组 dist,计算以速度 mid 行驶时,所需的总时间 time。
  5. 如果 time <= hour,说明当前速度可以满足要求,我们需要将 right 指针左移,将搜索范围从右半部分继续缩小。
  6. 如果 time > hour,说明当前速度过慢,我们需要将 left 指针右移,将搜索范围从左半部分继续缩小。
  7. 最终返回 left,即为最小的速度 x。

具体解题思路可以总结为以下几点:

  • 定义两个指针 left 和 right,分别指向可能的最小速度 1 和最大速度 10^7。
  • 使用二分查找的方法,不断缩小 left 和 right 的范围,直到 left > right 为止。
  • 在每次循环中,计算 mid = (left + right) // 2,表示当前的速度。
  • 遍历数组 dist,计算以速度 mid 行驶时,所需的总时间 time。
  • 如果 time <= hour,将 right 指针左移,将搜索范围从右半部分继续缩小。
  • 如果 time > hour,将 left 指针右移,将搜索范围从左半部分继续缩小。
  • 最终返回 left,即为最小的速度 x。

这种方法利用了二分查找的特性,不断缩小搜索范围,最终得到符合要求的最小速度 x。

以下为代码实现:

python 复制代码
class Solution:
    def minSpeedOnTime(self, dist: List[int], hour: float) -> int:
        left, right = 1, 10 ** 7
        while left <= right:
            mid = (left + right) // 2
            time = 0
            for i in range(len(dist) - 1):
                time += (dist[i] + mid - 1) // mid
            time += dist[-1] / mid
            if time <= hour:
                right = mid - 1
            else:
                left = mid + 1
        return left if len(dist) < hour + 1 else -1

时间复杂度: O(nlogm),其中 n 为距离数组 dist 的长度,m 为距离数组中的最大值。

空间复杂度:O(1),该算法只使用了常数级别的额外空间用于存储变量。

3. 在 D 天内送达包裹的能力

传送带上的包裹必须在 days 天内从一个港口运送到另一个港口。

传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量(weights)的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。

返回能在 days 天内将传送带上的所有包裹送达的船的最低运载能力。

真题点击此处:1011. 在 D 天内送达包裹的能力

解题思路:

  • 定义两个指针 left 和 right,分别指向货物重量的最大值和总和。
  • 使用二分查找的方法,不断缩小 left 和 right 的范围,直到 left > right 为止。
  • 在每次循环中,计算 mid = (left + right) // 2,表示当前的运载能力。
  • 遍历货物重量数组 weights,模拟运输过程,统计完成的运输批次 ans。
  • 根据 ans 与规定天数 days 的关系,调整 left 和 right 指针的位置。
  • 最终返回 left,即为最低的运载能力 x。

以下为代码实现:

python 复制代码
class Solution:
    def shipWithinDays(self, weights: List[int], days: int) -> int:
        left, right = max(weights), sum(weights)

        while left <= right:
            mid = (left + right) // 2
            ans = 0
            s = mid
            i = 0
            while i < len(weights):
                if s >= weights[i]:
                    s -= weights[i]
                    i += 1
                else:
                    ans += 1
                    s = mid
            ans += 1
            if ans <= days:
                right = mid - 1
            else:
                left = mid + 1
        return left

时间复杂度:O(nlogm),其中 n 为重量数组 weights 的长度,m 为所有重量的总和。

空间复杂度:O(1),该算法只使用了常数级别的额外空间用于存储变量。

相关推荐
生物信息与育种9 分钟前
黄三文院士领衔植物星球计划(PLANeT)发表Cell
人工智能·深度学习·算法·面试·transformer
aini_lovee16 分钟前
WSN 四大经典无需测距定位算法
算法
人道领域16 分钟前
【LeetCode刷题日记】掌握二叉树遍历:栈实现的三种绝妙方法
算法·leetcode·职场和发展
北冥湖畔的燕雀17 分钟前
深入解析Linux信号处理机制
算法
阿Y加油吧25 分钟前
二刷 LeetCode:动态规划经典双题复盘
算法·leetcode·动态规划
上弦月-编程40 分钟前
C语言指针超详细教程——从入门到精通(面向初学者)
java·数据结构·算法
莫等闲-42 分钟前
代码随想录一刷记录Day44——leetcode1143.最长公共子序列 53. 最大子序和
数据结构·c++·算法·leetcode·动态规划
生成论实验室43 分钟前
《事件关系阴阳博弈动力学:识势应势之道》第七篇:社会与情感关系——连接、表达与共鸣
人工智能·算法·架构·交互·创业创新
承渊政道1 小时前
【动态规划算法】(背包问题经典模型与解题套路)
数据结构·c++·学习·算法·leetcode·动态规划·哈希算法
yyy(十一月限定版)1 小时前
数电1对应latex代码
算法