Given an array of integers nums
and an integer threshold
, we will choose a positive integer divisor
, divide all the array by it, and sum the division's result. Find the smallest divisor
such that the result mentioned above is less than or equal to threshold
.
Each result of the division is rounded to the nearest integer greater than or equal to that element. (For example: 7/3 = 3
and 10/2 = 5
).
The test cases are generated so 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 of 7 (1+1+2+3) and if the divisor is 5 the sum will be 5 (1+1+1+2).
Example 2:
Input: nums = [44,22,33,11,1], threshold = 5
Output: 44
Constraints:
1 <= nums.length <= 5 * 10^4
1 <= nums[i] <= 10^6
nums.length <= threshold <= 10^6
def smallestDivisor(nums, threshold):
def check(divisor):
total_sum = 0
for num in nums:
total_sum += (num + divisor - 1) // divisor # Equivalent to math.ceil(num / divisor)
return total_sum <= threshold
left, right = 1, max(nums)
ans = right
while left <= right:
mid = left + (right - left) // 2
if check(mid):
ans = mid
right = mid - 1
else:
left = mid + 1
return ans
smallestDivisor(nums, threshold)
Function:
nums
and an integer threshold
as input.divisor
such that the sum of ceil(num / divisor)
for each num
in nums
is less than or equal to threshold
.check(divisor)
Helper Function:
divisor
as input.nums
by the divisor
.
total_sum += (num + divisor - 1) // divisor
efficiently computes the ceiling of the division.True
if the calculated total_sum
is less than or equal to the threshold
, and False
otherwise.Binary Search Initialization:
left = 1
: The smallest possible divisor is 1.right = max(nums)
: The largest possible divisor we need to consider is the maximum value in the input array.ans = right
: Initialize ans
to the maximum value as the initial possible answer.Binary Search Loop:
while left <= right
mid = left + (right - left) // 2
: Calculate the middle value to avoid potential integer overflow.if check(mid)
: If using mid
as the divisor results in a sum less than or equal to the threshold:
ans = mid
: Update ans
to the current mid
.right = mid - 1
: Try a smaller divisor to find the smallest possible one.else
:
left = mid + 1
: The current divisor mid
is too small, so try a larger divisor.Return Value:
ans
, which represents the smallest divisor that satisfies the given condition.Let's trace the execution with nums = [1, 2, 5, 9]
and threshold = 6
:
left = 1
, right = 9
, ans = 9
mid = 5
check(5)
: (1+5-1)//5 + (2+5-1)//5 + (5+5-1)//5 + (9+5-1)//5 = 1 + 1 + 1 + 2 = 5 <= 6
(True)ans = 5
, right = 4
mid = 2
check(2)
: (1+2-1)//2 + (2+2-1)//2 + (5+2-1)//2 + (9+2-1)//2 = 1 + 2 + 3 + 5 = 11 <= 6
(False)left = 3
mid = 3
check(3)
: (1+3-1)//3 + (2+3-1)//3 + (5+3-1)//3 + (9+3-1)//3 = 1 + 1 + 2 + 4 = 8 <= 6
(False)left = 4
mid = 4
check(4)
: (1+4-1)//4 + (2+4-1)//4 + (5+4-1)//4 + (9+4-1)//4 = 1 + 1 + 2 + 3 = 7 <= 6
(False)left = 5
left = 5
, right = 4
, left > right
ans = 5
nums
array and M is the maximum value in the nums
array. The binary search takes O(log M) time, and the check
function iterates through the nums
array in O(N) time.nums
is empty, the code will still work correctly because the sum in the check
function will be 0, which will likely be less than or equal to the threshold. It will return 1.nums
arrayA naive approach would be to iterate through possible divisors from 1 to the maximum value in nums
and check if the condition is satisfied. This has a time complexity of O(N * M) which is slower than binary search. Here's an example:
def smallestDivisor_brute_force(nums, threshold):
max_num = max(nums)
for divisor in range(1, max_num + 1):
total_sum = 0
for num in nums:
total_sum += (num + divisor - 1) // divisor
if total_sum <= threshold:
return divisor
The binary search approach is much more efficient, especially when the maximum value in nums
is large.