题目:
给你一个整数数组 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;
}
};
收获
这种极小极大化问题是常见的问题,一般都用二分法解题。
更多的类似题型
本文介绍了一种使用二分法解决整数数组划分问题的策略,通过最小化操作次数来达到开销最小化。通过实例和正确思路,展示了如何避免贪心算法的局限,转向更高效的方法来求解最小开销。
328

被折叠的 条评论
为什么被折叠?



