leetcode 1760. 袋子里最少数目的球

本文介绍了一种使用二分法解决整数数组划分问题的策略,通过最小化操作次数来达到开销最小化。通过实例和正确思路,展示了如何避免贪心算法的局限,转向更高效的方法来求解最小开销。

题目:

给你一个整数数组 nums ,其中 nums[i] 表示第 i 个袋子里球的数目。同时给你一个整数maxOperations 。你可以进行如下操作至多 maxOperations 次:
选择任意一个袋子,并将袋子里的球分到 2 个新的袋子中,每个袋子里都有正整数个球。
比方说,一个袋子里有5个球,你可以把它们分到两个新袋子里,分别有1个和 4 个球,或者分别有 2 个和 3 个球。
你的开销是单个袋子里球数目的最大值 ,你想要最小化开销。
请你返回进行上述操作后的最小开销。

示例:

输入:nums = [2,4,8,2], maxOperations = 4
输出:2
解释:

  • 将装有 8 个球的袋子分成装有 4 个和 4 个球的袋子。[2,4,8,2] -> [2,4,4,4,2] 。
  • 将装有 4 个球的袋子分成装有 2 个和 2 个球的袋子。[2,4,4,4,2] -> [2,2,2,4,4,2] 。
  • 将装有 4 个球的袋子分成装有 2 个和 2 个球的袋子。[2,2,2,4,4,2] -> [2,2,2,2,2,4,2] 。
  • 将装有 4 个球的袋子分成装有 2 个和 2 个球的袋子。[2,2,2,2,2,4,2] -> [2,2,2,2,2,2,2,2] 。
    装有最多球的袋子里装有 2 个球,所以开销为 2 并返回 2 。
  • 错误思路:做了快一个小时都没想出来,想要用堆和贪心算法来解决问题,但是一直做不出来。贪心算法每一次应该如何产生划分是一个难题。比如:

测试样例1:

nums = [7,17], maxOperations = 1
17=8+9, 返回9

测试样例2:

nums = [7,17], maxOperations = 2
17=10+7,10=5+5, 返回7

我们可以发现我们没有固定的划分策略,使得我们进行贪心操作是不可行的

  • 正确思路:采用二分法,不再拘泥于如何划分,而是将怎么划分问题转化为判定问题。给定预设的开销m和最大操作次数maxOperations,我们判断最终是否完成划分。
#include <iostream>
#include <algorithm>
using namespace std;

class Solution {
public:
    bool checkOperations(vector<int>& nums,int m,int maxOperations){
        int cnt=0,len=nums.size();
        for(int i=len-1;i>=0;i--){
            int p= (nums[i]-1)/m;
            cnt = cnt + p;
            if(cnt>maxOperations) break;
        }
        if (cnt<=maxOperations) return true;
        else return false;
    }
    int minimumSize(vector<int>& nums, int maxOperations) {
        int m;
        sort(nums.begin(),nums.end());
        int L=1,R=nums[nums.size()-1];
        while(L<R){
            m=(R-L)/2+L;
            if(checkOperations(nums,m,maxOperations)){
                R=m;
            }
            else{
                L=m+1;
            }
        }
        return R;

    }
};

收获

这种极小极大化问题是常见的问题,一般都用二分法解题。
更多的类似题型

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值