Find the Smallest Divisor Given a Threshold

medium binary search

Problem

You get an array of positive integers nums and an integer threshold. Pick a positive integer divisor d, divide every element by it, and round each quotient up; the cost of d is the sum of those ceilings. Return the smallest d whose cost is at most threshold (the inputs guarantee such a divisor exists).

Inputnums = [1, 2, 5, 9], threshold = 6
Output5
With d = 5 the sum is ⌈1/5⌉+⌈2/5⌉+⌈5/5⌉+⌈9/5⌉ = 1+1+1+2 = 5 ≤ 6, but d = 4 already gives 1+1+2+3 = 7 > 6.

def smallest_divisor(nums, threshold):
    def ceil_sum(d):
        return sum((x + d - 1) // d for x in nums)

    lo, hi = 1, max(nums)
    while lo < hi:
        mid = (lo + hi) // 2
        if ceil_sum(mid) <= threshold:
            hi = mid          # mid works; try a smaller divisor
        else:
            lo = mid + 1      # sum too big; divisor must grow
    return lo
function smallestDivisor(nums, threshold) {
  const ceilSum = (d) => nums.reduce((s, x) => s + Math.ceil(x / d), 0);
  let lo = 1, hi = Math.max(...nums);
  while (lo < hi) {
    const mid = (lo + hi) >> 1;
    if (ceilSum(mid) <= threshold) hi = mid; // mid works; try smaller
    else lo = mid + 1;                       // sum too big; grow d
  }
  return lo;
}
class Solution {
    public int smallestDivisor(int[] nums, int threshold) {
        int lo = 1, hi = 0;
        for (int x : nums) hi = Math.max(hi, x);
        while (lo < hi) {
            int mid = (lo + hi) >>> 1;
            int sum = 0;
            for (int x : nums) sum += (x + mid - 1) / mid;
            if (sum <= threshold) hi = mid;  // mid works; try smaller
            else lo = mid + 1;               // sum too big; grow d
        }
        return lo;
    }
}
int smallestDivisor(vector<int>& nums, int threshold) {
    int lo = 1, hi = *max_element(nums.begin(), nums.end());
    while (lo < hi) {
        int mid = lo + (hi - lo) / 2;
        long long sum = 0;
        for (int x : nums) sum += (x + mid - 1) / mid;
        if (sum <= threshold) hi = mid;   // mid works; try smaller
        else lo = mid + 1;                // sum too big; grow d
    }
    return lo;
}
Time: O(n log max(nums)) Space: O(1)