一、环境说明
- 本文是 LeetCode 1760题 : 袋子里最少数目的球,使用c语言实现
- 思路转换题,使用二分查找。
- 测试环境:Visual Studio 2019
二、代码展示
int minimumSize(int* nums, int numsSize, int maxOperations){
int left = 1,right = 0,mid = 0;
for(int i = 0;i<numsSize;i++){
if(right<nums[i]){//找到所有桶中最大值
right = nums[i];//最大值作为右边界
}
}
while(left<=right){
mid = left + ((right - left)>>1);//以mid为桶的最大值划分
long long opt = 0;//需要的拆分次数
for(int i = 0;i<numsSize;i++){
opt += (nums[i] - 1)/mid;//等于下面三行
//opt+=nums[i]/mid;//不能整除时,需要的拆分次数
//if(0==nums[i]%mid)//能整除时,少拆分一次。
// opt--;
}
if(opt > maxOperations){//操作次数太多了,增加每个桶的最大值,以减少操作次数
left = mid + 1;//左边界右移
}else{
right = mid -1;//右边界左移
}
}
return left;//返回划分后,桶中最大值
}
三、思路分析
- 二分查找。
- 给定操作次数,求每个袋子最小的装球数。转换题意,求将每个袋子球数变成最少值,需要的opt次数。
- 二分查找以mid为桶的最大值,进行操作。操作次数=每个桶的装球数/桶的最大值。注意,如果能整除,如9/3 = 3,实际只用划分2次,如果不能整除,如10/3=3,实际要划分3次,这个判定等价于(nums[i]-1)/mid。
- opt+=(nums[i]-1)/mid,表示按照当前mid总共需要的opt的次数
- 当操作数opt>maxOperations时,说明mid取值小了,让left = mid +1。
- 最后我们找到的left就是刚好满足opt = maxOperations的最小桶数。
四、代码分析
- 理解思路很重要!
- 博主欢迎读者在评论区留言,作为日更博主,看到就会回复的。
五、AC

六、复杂度分析
- 时间复杂度:O(nlog|C|) ,n是nums数组的大小,|C|是初始状态下,所有桶中的最大值。遍历nums,同时二分查找划分后桶最大值的时间复杂度是O(nlog|C|)
- 空间复杂度:O(1),除了若干变量使用的常数空间,没有额外使用线性空间。
版权声明:本文为Innocence02原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。