LC1760.袋子里最少数目的球

原题链接
image.png

思路:

  • 二分查找解决最值问题
  • 首先,转化成判断问题:给定maxOperations次,能不能使得所有袋子球的最大值不超过y个。
  • 如果y变大了,那么需要的操作次数将会下降。二段性由此确定。袋子里面允许的最大值越多,需要的操作次数就越少。说明,存在一个最小的y,能够满足总次数<= maxOperations。(相当于找右区间的左端点)
  • 对于“操作次数”数组而言,相当于取右半边数组的左侧端点。
  • 假如一个袋子里面有x个球,拆分成若干个袋子,需要使得最大值<= y,需要操作的最少次数是多少?本质上就是一个向上取整的问题。

    • image.png
    • LC1760.袋子里最少数目的球 - 图3

      代码:

      1. class Solution {
      2. public:
      3. bool check(int cost, vector<int>& nums, int maxOperations) {
      4. long long all_operations = 0;
      5. for (int num : nums) {
      6. all_operations += (num - 1) / cost;
      7. }
      8. return all_operations <= (long long)(maxOperations);
      9. }
      10. int minimumSize(vector<int>& nums, int maxOperations) {
      11. // 假如我对开销没啥要求,再多都没事,那么maxOperations会变低
      12. // 逐步要求开销小,那么maxOperations慢慢上升,直到上升到题目要求的数字
      13. // 相当于取右半边数组的左端点。
      14. // left, right 代表的都是开销,即最少数量的球的个数
      15. int left = 1, right = 1e9 + 5;
      16. while (left < right) {
      17. int mid = (left + right) / 2;
      18. if (check(mid, nums, maxOperations)) {
      19. right = mid;
      20. } else {
      21. left = mid + 1;
      22. }
      23. }
      24. return left;
      25. }
      26. };