➗ 使结果不超过阈值的最小除数
📝 题目描述
给你一个正整数数组nums
和一个正整数threshold
,你需要自行选择一个正整数作为除数,然后将数组里的每个数都除以它,并对所有的除法结果累加求和。
请你找出能够使上述结果小于等于阈值threshold
的除数中最小的那个。
需要说明的是,数组中的每个数除以除数后都向上取整,比方说
题目保证一定有解,即threshold >= nums.length
。
📋 代码模板
java
class Solution {
public int smallestDivisor(int[] nums, int threshold) {
}
}
typescript
function smallestDivisor(nums: number[], threshold: number): number {
}
💡 提示
🚀 示例
🖊️ 题解
设正整数除数为
根据上述单调性,我们可以使用二分查找算法,找出满足条件
二分查找的下限可以设置为
综上所述,在区间
为了进一步提高算法效率,我们还可以对
java
class Solution {
public int smallestDivisor(int[] nums, int threshold) {
int low = 1, high = nums[0];
for (int num : nums) {
high = Math.max(num, high);
}
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (check(nums, threshold, mid)) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low;
}
private boolean check(int[] nums, int threshold, int div) {
int total = 0;
for (int i = 0; i < nums.length && total <= threshold; i++) {
total += (nums[i] + div - 1) / div;
}
return total <= threshold;
}
}
typescript
function smallestDivisor(nums: number[], threshold: number): number {
const check = (div: number): boolean => {
let total = 0;
for (let i = 0; i < nums.length && total <= threshold; i++) {
total += Math.ceil(nums[i] / div);
}
return total <= threshold;
}
let low = 1, high = Math.max(...nums);
while (low <= high) {
const mid = low + Math.floor((high - low) / 2);
if (check(mid)) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low;
}
💭 复杂度分析
基于二分查找
的解决方案的复杂度分析如下。
- 时间复杂度:
。其中 为 数组中的最大值, 为数组长度。 - 空间复杂度:
。