题目大意:
使结果不超过阈值的最小除数
给你一个整数数组 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
如果想查看本题目是哪家公司的面试题,请参考以下免费链接: https://leetcode.jp/problemdetail.php?id=1283
解题思路分析:
这是一道典型的并且容易联想到使用二分查找来解题的题目。二分查找的范围在1到max之间。max为数组中的最大数。我们利用这些数字作为除数,用每个数字除以当前除数,算出所有商的和,与threshold比较,如果和大于threshold,需要减小和,也就是相应增大除数,反之减小除数。编写二分查找时注意边界问题。
实现代码:
public int smallestDivisor(int[] nums, int threshold) { int max = -1; // 数组中的最大数 // 找到数组中的最大数 for (int n : nums) max = Math.max(max, n); // 左边界为1,右边界为数组中最大数,开始二分查找 int left=1, right=max; while(left<right){ // 中间值 int mid=(left+right)/2; // 求所有商的和 int sum=0; for(int n : nums){ sum+=((n+mid-1) / mid); } // 如果和小于等于threshold,增大除数 if(sum<=threshold){ right=mid; }else{ // 反之,减少除数 left=mid+1; } } return left; }
本题解法执行时间为10ms。
Runtime: 10 ms, faster than 100.00% of Java online submissions for Find the Smallest Divisor Given a Threshold.
Memory Usage: 42.9 MB, less than 100.00% of Java online submissions for Find the Smallest Divisor Given a Threshold.
本网站文章均为原创内容,并可随意转载,但请标明本文链接如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: http://leetcode.jp/leetcode-1283-find-the-smallest-divisor-given-a-threshold-解题思路分析/