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;
};

 

posted @ 2019-12-08 20:20  土豆zhang  阅读(339)  评论(0编辑  收藏  举报