20250212-leetcode1760袋子里最少的球-
解题思路
这道题可以使用二分查找来解决:
题目分析:
- 我们需要找到一个最小值 x,使得所有袋子里的球数都不超过 x
- 对于每个袋子,如果球数超过 x,需要进行分割操作
- 分割操作次数不能超过 maxOperations
二分查找思路:
- 对于给定的目标值 x,可以计算需要多少次操作才能使所有袋子的球数 ≤ x
- 如果操作次数 ≤ maxOperations,说明 x 可能还可以更小
- 如果操作次数 > maxOperations,说明 x 必须更大
关键点:
- 二分查找的左边界是 1
- 右边界是数组中的最大值
- 对于每个 x,计算需要的操作次数
代码实现
1 | class Solution: |
代码解释
check(mid)
函数:- 计算将所有球数控制在mid以下需要的操作次数
- 对于每个袋子,需要的操作次数是
(num-1) // mid
- 如果总操作次数 ≤ maxOperations,返回True
二分查找过程:
- 初始范围:
[1, max(nums)]
- 每次取中间值mid
- 根据check(mid)的结果缩小范围
- 最终找到满足条件的最小值
- 初始范围:
复杂度分析
时间复杂度:O(n * log M)
- n 是数组长度
- M 是数组中的最大值
- 二分查找需要 log M 次迭代
- 每次迭代需要 O(n) 时间计算操作次数
空间复杂度:O(1)
- 只使用了常数额外空间
总结
这是一道典型的二分查找应用题。关键在于:
- 将问题转化为判定性问题
- 设计合适的判定函数
- 正确处理二分查找的边界条件
关键代码详解
1 | operations = sum((num - 1) // mid for num in nums) |
这行代码计算需要多少次操作才能使所有袋子的球数不超过mid。让我们逐部分分析:
(num - 1) // mid
的含义:- 假设一个袋子有 num 个球,目标是将其分成若干个不超过 mid 的小袋
- 例如:num = 9, mid = 3
- (9-1) // 3 = 8 // 3 = 2,表示需要2次操作
- 第一次:9 -> [3,6]
- 第二次:6 -> [3,3]
- 最终:[3,3,3]
为什么是
(num - 1) // mid
:- 如果 num = 7, mid = 3
- (7-1) // 3 = 6 // 3 = 2 次操作
- 第一次:7 -> [3,4]
- 第二次:4 -> [3,1]
- 最终:[3,3,1]
整数除法
//
的作用:- 向下取整,确保得到最少需要的操作次数
- 例如:5/2 = 2.5,而 5//2 = 2
列表推导式
for num in nums
:- 对数组中的每个数字都进行上述计算
sum()
函数:- 将所有需要的操作次数加总
- 得到处理整个数组需要的总操作次数
示例:
1 | nums = [9, 5] |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Never Settle!
评论