Find the Smallest Divisor Given a Threshold

medium

You are given an array of positive integers nums and an integer threshold.

Choose a positive integer divisor, divide every element of nums by it, and add up the results — where each division is rounded up to the nearest integer (so 7 / 3 counts as 3, and 10 / 2 is 5).

Return the smallest divisor such that this sum is less than or equal to threshold.

It is guaranteed that an answer always exists.

Hints

Compute the sum for divisor 1, then for a huge divisor like max(nums). Which direction does the sum move as the divisor grows?
The sum never increases as the divisor increases — so the candidates split into a block that fails followed by a block that fits. You want the first divisor that fits.
A monotone fails-then-fits boundary over the range 1..max(nums) is exactly what lower-bound binary search finds: probe the middle divisor, check its O(n) sum, and halve the range.

Common doubts

At d = max(nums) every term ceil(nums[i] / d) is exactly 1, so the sum equals nums.length — and the constraint nums.length <= threshold guarantees that fits. Any larger divisor still gives all 1s, so nothing beyond max(nums) can ever do better.
For positive integers, ceil(x / d) equals (x + d - 1) // d. Adding d - 1 pushes any nonzero remainder over to the next integer, and it avoids float precision issues entirely.
With divisor 1 the sum is the plain array sum — up to 5 * 10^4 * 10^6 = 5 * 10^10, which overflows 32-bit integers. Accumulate in long long in C++; Python, JavaScript numbers, and Go's 64-bit int are fine.
We never search nums — we search the range of candidate divisors 1..max(nums). What must be monotone is the feasibility check sum(d) <= threshold as a function of d, and it is: a bigger divisor never increases the sum.

Interview follow-ups

It is the identical skeleton: binary search the eating speed k in 1..max(piles), where the feasibility check is whether sum(ceil(pile / k)) hours fits within h. Recognising the shared fails-then-fits shape is the interview win.
The sum is still non-increasing in the divisor, so the exact same binary search works — only the per-term formula changes to x // d. The habit to build: re-verify monotonicity whenever the cost function changes, because that is the only property the search needs.
Same monotone structure viewed from the other side: the predicate flips from true to false as the divisor grows, so you binary search for the last true — an upper-bound search instead of a lower-bound one.

Fun facts

  • The thing being searched here is invisible: no array is ever sorted, but the answer space is monotone. That mental shift — from binary-searching data to binary-searching answers — unlocks a whole family of problems.
  • The integer trick (x + d - 1) // d for ceiling division is a classic from low-level systems code, where it computes how many fixed-size blocks are needed to hold x bytes.
  • The same fails-then-fits template solves Koko Eating Bananas, Capacity to Ship Packages Within D Days, Minimum Days to Make Bouquets, Aggressive Cows, and Split Array Largest Sum — one pattern, five classics.

Asked at

AmazonGoogleMicrosoftAdobe
Frequently Sometimes Occasionally
Example 1
Input: nums = [1,2,5,9], threshold = 6
Output: 5
With divisor 1 the sum is 17 (1+2+5+9). With divisor 4 it is 7 (1+1+2+3) — still too big. With divisor 5 it is 5 (1+1+1+2), which fits, and no smaller divisor works.
Example 2
Input: nums = [44,22,33,11,1], threshold = 5
Output: 44
The sum can never drop below 5 — each of the 5 elements contributes at least 1. So every element must shrink to exactly 1, and that first happens at divisor 44 (since ceil(44/43) = 2 is still too much).
Constraints

- 1 <= nums.length <= 5 * 10^4 - 1 <= nums[i] <= 10^6 - nums.length <= threshold <= 10^6

Solve this problem →