[LeetCode] 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, 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

这道题给了一个整型数组 nums,一个正整数 threshold,让找到一个最小的除数,使得数组中的每个数字除以这个 divisor 的商之和小于等于给定的 threshold。这里对于除不尽的情况下是采取 ceiling 的取整方式,而且题目中说了一定会有解。通过观察题目中给的例子不难理解题意,现在再来想一想需要返回的这个数有没有什么范围,首先题目中说了必须是一个正数,而最小的正数是1,什么情况下可能返回1呢?数组中所有的数字除以1都是其本身,那么商之和就等于数组之和,即原数组之和小于等于 threshold 时,就可以返回1,这是返回值的最小值。而最大值则可以取到数组中的最大值,因为再大就没有意义了,得到的商还是1,即商之和为数组的元素个数,其必定小于等于 threshold,因为题目说一定有解。

返回值的范围有了,为 [1, 10^6],可以发现是有序的,那么隐隐约约可以感觉到应该可以用二分搜索法来查找吧,因为一个一个的检测实在是不高效,当得到二分搜索的中间值 mid 时,遍历数组中的每个数字,计算商。由于需要在不能整除时进行 ceiling 取整,这里可以使用一个小 trick,先給 num 加上一个 mid-1, 然后再除以 mid,这样就是得到 ceiling 取整的结果了,对于可以整除的 num,得到还是整除后的商,并不会改变。然后用商之和 sum 跟 threshold 进行比较,若大于 threshold,则表示除数小了,将 left 更新为 mid+1,反之,则将 right 更新为 mid,最终的结果保存在了 left 中。这道题是博主的总结帖 LeetCode Binary Search Summary 二分搜索法小结 中的第四类,参见代码如下:


class Solution {
public:
    int smallestDivisor(vector<int>& nums, int threshold) {
        int left = 1, right = 1e6;
        while (left < right) {
            int mid = left + (right - left) / 2, sum = 0;
            for (int num : nums) {
                sum += (num + mid - 1) / mid;
            }
            if (sum > threshold) left = mid + 1;
            else right = mid;
        }
        return left;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1283


类似题目:

Minimized Maximum of Products Distributed to Any Store


参考资料:

https://leetcode.com/problems/find-the-smallest-divisor-given-a-threshold/

https://leetcode.com/problems/find-the-smallest-divisor-given-a-threshold/discuss/446376/JavaC%2B%2BPython-Binary-Search


LeetCode All in One 题目讲解汇总(持续更新中...)

posted @ 2022-01-17 20:34  Grandyang  阅读(343)  评论(0编辑  收藏  举报
Fork me on GitHub