1283. 使结果不超过阈值的最小除数
大约 3 分钟
---
1283. 使结果不超过阈值的最小除数
- 标签:数组、二分查找
- 难度:中等
题目链接
题目大意
描述:给你一个整数数组 和一个正整数 ,你需要选择一个正整数作为除数,然后将数组里每个数都除以它,并对除法结果求和(向上取整)。例如 ,。
要求:找出能够使上述结果小于等于阈值 的除数中最小的那个。题目保证一定有解。
说明:
- 。
- 。
- 。
示例:
- 示例 1:
输入:nums = [1,2,5,9], threshold = 6
输出:5
解释:如果除数为 1,我们可以得到和为 17(1+2+5+9)。
如果除数为 4,我们可以得到和为 7(1+1+2+3)。如果除数为 5,和为 5(1+1+1+2)。- 示例 2:
输入:nums = [2,3,5,7,11], threshold = 11
输出:3解题思路
思路 1:二分查找
1. 核心思想
这道题的关键是观察到单调性:除数越大,每个数除完向上取整后的和就越小。反之亦然。
利用这个单调性,我们可以用二分查找来找到临界点——最小的那个满足「和 」的除数。
为什么用二分而不是从 开始逐步增大?因为 ,如果线性扫描最坏可能需要尝试 次,而二分只需要 次。
2. 具体步骤
第 1 步:确定二分范围
- 下界 :除数的可能最小值。
- 上界 :因为当除数 最大值时,每个数除完向上取整的结果都是 ,总和 。题目保证 ,所以这个除数一定满足条件。更小的除数可能也满足,所以这是搜索边界。
第 2 步:二分查找
使用「找最小值」模板:
- 当 时循环:
- 取 。
- 计算以 为除数的结果和 。
- 如果 ,说明 可行,尝试更小的除数:。
- 否则 ,需要增大除数:。
第 3 步:返回结果
就是最小的满足条件的除数。
结合示例 1 走一遍:
- : →
- : →
- : →
- ,返回 。
思路 1:代码
class Solution:
def smallestDivisor(self, nums: List[int], threshold: int) -> int:
# 二分查找范围
left, right = 1, max(nums)
while left < right:
mid = (left + right) // 2
# 计算以 mid 为除数时每个数除完向上取整的和
# (num + mid - 1) // mid 是向上取整的常用技巧
total = sum((num + mid - 1) // mid for num in nums)
if total <= threshold:
right = mid # mid 可行,但也许可以更小,向左收缩
else:
left = mid + 1 # 和太大了,需要更大的除数
return left思路 1:复杂度分析
- 时间复杂度:,其中 是数组 的长度,。二分查找进行 轮,每轮需要 时间求和。
- 空间复杂度:,只使用了常数个变量。