二分搜索类问题的分析
1、找出隐藏的函数关系,呈单调递增或递减
2、找出x和f(x),一般所求即为x
3、确定最小、最大,采用哪种二分搜索方式
4、进行主函数编写查找
1、珂珂吃香蕉
分析:
自变量x:为v,故遍历数组为v的数组,f(x)表示时间
由于找的最小v,故使用左侧二分查找
先构造一个函数求hours,然后返回主函数进行二分搜索
代码实现
int minEatingSpeed(int* piles, int pilesSize, int h){
int left = 1;
int right = 1000000000 + 1;
while(left < right)
{
int mid = left + (right - left)/2;
if (f(piles,mid,pilesSize) <= h)
{
right = mid;
}
else
{
left = mid + 1;
}
}
return left;
}
int f(int *piles,int x,int pilesSize)
{
int hours = 0;
for (int i=0;i<pilesSize;i++)
{
hours += piles[i] / x;
if (piles[i] % x > 0)
{
hours++;
}
}
return hours;
}
2、在第D天送达包裹的能力
分析:最低运载能力----x
f(x)----天数
二者呈单调递增关系
1、构造函数求出天数
int f(int *weights,int x,int weightsSize)
{
int days = 0;
for (int i=0;i<weightsSize;)
{
int cap = x;
while( i < weightsSize)
{
if (cap < weights[i]) break;
else{
cap -= weights[i];
}
i++;
}
days++;
}
return days;
}
2、编写主函数
注意:在for循环中为确定载重的区间,最小(left)为数组中的最大值,最大(right)为数组中所有值相加
int shipWithinDays(int* weights, int weightsSize, int days){
int left = 0;
int right = 1;
int max = 0;
for (int i=0;i<weightsSize;i++)
{
if (weights[i] > max)
{
max = weights[i];
}
right += max;
}
left = max;
while(left < right)
{
int mid = left + (right-left)/2;
if (f(weights,mid,weightsSize) <= days)
{
right = mid;
}
else
{
left = mid + 1;
}
}
return left;
}