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
// 先是暴力循环,测试用例执行超时,后来用二分法没做出来
/**
 * @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;
};
02-12 18:17
查看更多