1. 问题描述:
给你一个整数数组 nums 和一个正整数 threshold ,你需要选择一个正整数作为除数,然后将数组里每个数都除以它,并对除法结果求和。
请你找出能够使上述结果小于等于阈值 threshold 的除数中最小的那个。
每个数除以除数后都向上取整,比方说 7/3 = 3 , 10/2 = 5 。
题目保证一定有解。
示例 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
示例 3:
输入:nums = [19], threshold = 5
输出:4
提示:
1 <= nums.length <= 5 * 10^4
1 <= nums[i] <= 10^6
nums.length <= threshold <= 10^6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-the-smallest-divisor-given-a-threshold
2. 思路分析:
① 首先需要读懂题目,题目的主要意思是找到一个除数,使得数组中所有元素除以这个除数结果的的累加和小于等于threshold,并且假如有多个结果相同的话那么返回最小的除数
② 从题目可以知道题目是有解的,所以可以知道最大的除数为数组元素的最大值,所以我们需要对给出的数组进行排序数组的最后一个元素就是最大值,然后我们可以使用二分查找的思想来找到这个除数,l在一开始的时候为1,r在为数组元素的最大值,当除以整个除数的时候发现累加的结果太大了那么需要将l向右移动,否则向左移动
3. 代码如下:
class Solution {
public int smallestDivisor(int[] nums, int threshold) {
Arrays.sort(nums);
int sum = 0, mid = 0;
/*因为是需要找到最小的那个*/
int res = 0;
int l = 1, r = nums[nums.length - 1];
while (l <= r){
sum = 0;
mid = (l + r) / 2;
for (int i = 0; i < nums.length; ++i){
//sum += nums[i] % mid == 0 ? nums[i] / mid : nums[i] / mid + 1;
sum += (nums[i] - 1) / mid + 1;
}
/*因为要找到最小的那个所以需要使用一个变量来记录*/
if (sum <= threshold) {
res = mid;
r = mid - 1;
}
else l = mid + 1;
}
return res;
}
}