class Solution:
def smallestDivisor(self, nums, threshold):
import math
def compute_sum(divisor):
return sum((num + divisor - 1) // divisor for num in nums)
left, right = 1, max(nums)
answer = right
while left <= right:
mid = (left + right) // 2
if compute_sum(mid) <= threshold:
answer = mid
right = mid - 1
else:
left = mid + 1
return answer
class Solution {
public:
int smallestDivisor(vector<int>& nums, int threshold) {
auto compute_sum = [&](int divisor) {
int total = 0;
for (int num : nums) {
total += (num + divisor - 1) / divisor;
}
return total;
};
int left = 1, right = *max_element(nums.begin(), nums.end());
int answer = right;
while (left <= right) {
int mid = left + (right - left) / 2;
if (compute_sum(mid) <= threshold) {
answer = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return answer;
}
};
class Solution {
public int smallestDivisor(int[] nums, int threshold) {
int left = 1, right = 0;
for (int num : nums) {
right = Math.max(right, num);
}
int answer = right;
while (left <= right) {
int mid = left + (right - left) / 2;
int total = 0;
for (int num : nums) {
total += (num + mid - 1) / mid;
}
if (total <= threshold) {
answer = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return answer;
}
}
var smallestDivisor = function(nums, threshold) {
const computeSum = (divisor) => {
let total = 0;
for (let num of nums) {
total += Math.floor((num + divisor - 1) / divisor);
}
return total;
};
let left = 1, right = Math.max(...nums);
let answer = right;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (computeSum(mid) <= threshold) {
answer = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return answer;
};
Given an array of positive integers nums
and an integer threshold
, your goal is to find the smallest positive integer divisor such that the sum of all the elements in nums
divided by this divisor (and rounded up to the nearest integer for each element) is less than or equal to threshold
.
In other words, for each number num
in nums
, compute ceil(num / divisor)
, sum all these values, and make sure the total does not exceed threshold
. You need to find the smallest possible divisor that satisfies this condition.
At first glance, it seems like you might have to try every possible divisor from 1 up to the largest number in nums
and check if it meets the condition. However, this would be inefficient, especially for large arrays or large numbers.
We notice that as the divisor increases, the result of ceil(num / divisor)
for each num
decreases or stays the same. This means that the total sum of these values will decrease as the divisor increases. This monotonic (always decreasing or staying the same) property hints that we can use binary search to find the smallest divisor efficiently.
Instead of brute-forcing every possible divisor, we can repeatedly narrow down the range of possible divisors by checking the mid-point, similar to how you might guess a number in a "higher or lower" game.
nums
(which gives the smallest possible sum).left <= right
), do the following:mid
) of the current range.num
in nums
, compute ceil(num / mid)
(or equivalently, (num + mid - 1) // mid
without using floating point).threshold
, try a smaller divisor by moving the right boundary to mid - 1
.mid + 1
.
Sample Input:
nums = [1, 2, 5, 9]
, threshold = 6
So, the smallest divisor is 5.
The key insight is recognizing the monotonic relationship between the divisor and the total sum of rounded-up divisions. This enables a binary search for efficiency, reducing the time complexity from potentially millions of checks to just a few dozen, even for large inputs. The approach is elegant because it leverages mathematical properties (monotonicity) and simple integer math to avoid floating-point issues, resulting in a robust and fast solution.