leetcode4
使结果不超过阈值的最小除数
给你一个整数数组 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
// 先是暴力循环,测试用例执行超时,后来用二分法没做出来
// 当时尝试中也尝试,结果+1 或者 结果-1,因为有个测试用例正好mid+1,但是,通过观察答案,它是left+1 或者是 right+1, 究其原因还是二分法还是没熟练得应用到实践 /** * @param {number[]} nums * @param {number} threshold * @return {number} */ var smallestDivisor = function(nums, threshold) { let len = nums.length; let max = Math.max(...nums); let n=0; let result; let left = 1; let right = max; if(len>=threshold){ return max; }else{ while(true){ let mid = Math.floor((right+left)/2) let res = nums.reduce((init, val)=>init+Math.ceil(val/mid), 0); if(res < threshold) { right = mid } else if(res > threshold){ left = mid } else if(res === threshold) { result = mid break; } if(mid === left ){ result = mid break; } if(mid === right){ result = mid break; } } } return result };
class Solution { public: int smallestDivisor(vector<int>& nums, int threshold) { int L = 1, R = 1000001; int ret = R; while (L <= R) { int m = (L+R)/2; long long sum = 0; for (auto x : nums) sum += x/m+(x%m != 0); if (sum <= threshold) { ret = m; R = m-1; } else L = m+1; } return ret; } };
/** * @param {number[]} nums * @param {number} threshold * @return {number} */ var smallestDivisor = function(nums, threshold) { let lo = 1 let hi = 1e6 while(lo <= hi) { let mi = lo + Math.floor((hi - lo) / 2) let c = check(mi) // consol/e.log(mi, '->', c) if (c > threshold) { lo = mi + 1 } else { hi = mi - 1 } } return hi + 1 function check(d) { let ans = 0 for(const num of nums) { ans += Math.ceil(num / d) } return ans } };
/** * @param {number[]} nums * @param {number} threshold * @return {number} */ var smallestDivisor = function(nums, threshold) { let l = 0; let r = 1000000; while (l < r) { const m = Math.round((l + r) / 2); let sum = 0; for (let i = 0; i < nums.length; i++) { sum += Math.ceil(nums[i] / m); } if (sum <= threshold) { r = m - 1; } else { l = m; } } return l + 1; };