1283. Find the Smallest Divisor Given a Threshold

Given an array of integers nums and an integer threshold, we will choose a positive integer divisor and divide all the array by it and sum the result of the division. Find the smallest divisor such that the result mentioned above is less than or equal to threshold.

Each result of division is rounded to the nearest integer greater than or equal to that element. (For example: 7/3 = 3 and 10/2 = 5).

It is guaranteed that there will be an answer.

Example 1:

Input: nums = [1,2,5,9], threshold = 6
Output: 5
Explanation: We can get a sum to 17 (1+2+5+9) if the divisor is 1. 
If the divisor is 4 we can get a sum to 7 (1+1+2+3) and if the divisor is 5 the sum will be 5 (1+1+1+2). 

Example 2:

Input: nums = [2,3,5,7,11], threshold = 11
Output: 3

Example 3:

Input: nums = [19], threshold = 5
Output: 4

Constraints:

  • 1 <= nums.length <= 5 * 10^4
  • 1 <= nums[i] <= 10^6
  • nums.length <= threshold <= 10^6
class Solution {
    public int smallestDivisor(int[] nums, int threshold) {
        Arrays.sort(nums);
        int max = nums[nums.length - 1];
        int res = Integer.MAX_VALUE;
        for(int i = 1; i <= max; i++){
            int sum = 0;
            for(int j = 0; j < nums.length; j++){
                if(nums[j] < i) sum += 1;
                else if(nums[j] % i == 0) sum += nums[j] / i;
                else sum += nums[j] / i + 1;
            }
            if(threshold >= sum){
                res = Math.min(i, res);
            }
        }
        return res;
    }
}

O(n2) TLE sadly.

再看了hint,发现是二分法,想来也对。

首先在除法种除数divisor越小,商越大。我们是要商的sum小于threshold的前提下,所有divisor的sum最小,

从中间开始,如果得到商的sum大于thresold说明除数太小了,mid+1,

如果sum小于threshold说明还可以接受,mid-1

class Solution {
    public int smallestDivisor(int[] nums, int threshold) {
        Arrays.sort(nums);
        int right = nums[nums.length - 1];
        int left = 1;
        while(left < right){
            int m = left + (right - left)/2, sum = 0;
            for(int j = 0; j < nums.length; j++){
            if(nums[j] % m == 0) sum += nums[j] / m;
                else sum += nums[j] / m + 1;
            }
            if(sum > threshold) left = m + 1;
            else right = m;
        }
        return left;
    }
}

方法2,pass,有点慢,因为用了sort方法

class Solution {
    public int smallestDivisor(int[] nums, int threshold) {
        
        int right = (int)1e6;
        int left = 1;
        while(left < right){
            int m = left + (right - left)/2, sum = 0;
            for(int j = 0; j < nums.length; j++){
            if(nums[j] % m == 0) sum += nums[j] / m;
                else sum += nums[j] / m + 1;
            }
            //for(int i : nums) sum += (i + m - 1) / m;
            if(sum > threshold) left = m + 1;
            else right = m;
        }
        return left;
    }
}

方法3,快了点

 public int smallestDivisor(int[] A, int threshold) {
        int left = 1, right = (int)1e6;
        while (left < right) {
            int m = (left + right) / 2, sum = 0;
            for (int i : A)
                sum += (i + m - 1) / m;
            if (sum > threshold)
                left = m + 1;
            else
                right = m;
        }
        return left;
    }

方法4最快,来自https://leetcode.com/problems/find-the-smallest-divisor-given-a-threshold/discuss/446376/JavaC%2B%2BPython-Binary-Search

原文地址:https://www.cnblogs.com/wentiliangkaihua/p/12065983.html