1、题目描述
力扣原题:原题链接
优秀题解:二分搜索类问题
2、代码:
class Solution {
public int maximumCandies(int[] candies, long k) {
//二分法 分糖果
int max = candies[0];
for(int candy:candies) max = Math.max(max,candy);
//每个孩子最多能分max个糖果
int left =0,right=max;
while(left<right){
//右边主动收缩应该主动偏右
int mid = left+(right-left+1)/2;
if(getkids(candies,mid)<k){
//减治法 不行的先排除
//不够分这么多孩子,那么每个孩子分少一点 向左查找
right = mid-1;
}else{
//刚好够分或者分多了 向右查找 目的是找到每个孩子可以分到的最大糖果数目
left=mid;
}
}
return left;
}
//当 每个孩子分candiansNum颗糖果时,最多可以分给几个孩子
private long getkids(int[] candies,int candiedNum){
long count =0;
for(int candy:candies){
count += candy/candiedNum;
}
return count;
}
}
优秀题解2
力扣https://leetcode-cn.com/problems/maximum-candies-allocated-to-k-children/solution/5219-mei-ge-xiao-hai-zui-duo-neng-fen-da-375p/解题思路
1.计算出总共有多少糖果
2.计算每个孩子理论上平均能分多少个糖果
3.遍历数组,找到满足条件的最大值
4.二分优化
class Solution {
public int maximumCandies(int[] candies, long k) {
long sum=0L;
for(int i:candies){ //求和
sum+=(long)(i);
}
if(sum<k){
return 0;
}
if(sum==k){
return 1;
}
long max=sum/k; //求平均值
for(long i=max;i>=0;i--){ //从最大值开始遍历,
long cnt=0l;
for(int num:candies){
cnt+=(long)(num)/i; //看num能分出几个i
}
if(cnt>=k){ //直到找到第一个满足条件的最大值,返回
return (int)i;
}
}
return 0;
}
}
===================================================================》
分割线
=============================
类型题目2 : 完成旅行的最少时间
1、原题地址:
力扣原题链接https://leetcode-cn.com/problems/minimum-time-to-complete-trips/
2、解题思路
怎么想到二分法的!!!!!
对花费的时间进行二分查找
初始最小时间为0,最大时间为只用一辆速度最快的车跑完所有旅途花费的时间
取中间时间mid,求mid内能完成得旅途数目trips
1.若trips>=totalTrips,表明时间还可以优化,部分车可能多跑了,向左查找right=mid
2.若trips<totalTrips,表明时间不足,全部车出动了旅途还没跑完,向右查找left=mid+1
坑点:注意返回类型为long
时间复杂度:O(MlogN),空间复杂度:O(1)
class Solution {
public long minimumTime(int[] time, int totalTrips) {
/*
怎么想到二分法的!!!!!
对花费的时间进行二分查找
初始最小时间为0,最大时间为只用一辆速度最快的车跑完所有旅途花费的时间
取中间时间mid,求mid内能完成得旅途数目trips
1.若trips>=totalTrips,表明时间还可以优化,部分车可能多跑了,向左查找right=mid
2.若trips<totalTrips,表明时间不足,全部车出动了旅途还没跑完,向右查找left=mid+1
坑点:注意返回类型为long
时间复杂度:O(MlogN),空间复杂度:O(1)
*/
// 先将时间排序
Arrays.sort(time);
// 计算最长时间:全部旅途都用速度最快的一辆车跑完
long right = 1L * time[0] * totalTrips;
long left = 0;
// 进行二分查找
while(left < right) {
long mid = (left + right) >>> 1;
// 计算mid时间能走的旅途次数
long trips = 0;
for(int t : time) {
// 当mid时间不足以完成一趟旅途,接下来的车更不可能,退出
if(mid < t) {
break;
}
// 累加每辆车在mid时间内能完成的旅行次数
trips += mid / t;
}
// 判断trips与totalTrips的大小关系进行转移
if(trips >= totalTrips) {
// 旅途数超标,时间还可以再优化,向左查找
right = mid;
}else {
// 旅途数不足,时间不足,向右查找
left = mid + 1;
}
}
// 最后left=right,任意返回一个即可
return left;
}
}