二分查找的目的是优化时间复杂度,防止时间超过.因此在一些有时间限制的题目上,使用二分查找是一个不错的选择.
二分查找,也称为折半查找,是一种在有序数组中查找特定元素的搜索算法。其核心思想是将数组不断对半分割,比较中间元素与目标值的大小,以此缩小搜索范围。步骤如下:
定义查找区域的左边界left和右边界right,以及中间位置middle。
比较中间元素middle与目标值target。如果middle等于target,则查找成功,返回middle。
如果middle大于target,则在数组的左半部分继续查找,更新right为middle-1。
如果middle小于target,则在数组的右半部分继续查找,更新left为middle+1。
重复以上步骤直到找到目标值或确定目标值不存在于数组中。
如果通过上面的方法去编写代码其中mid的+1和-1,每次需要思考,还容易出错.因此使用下面这个模板会让编写的过程变得更加轻松.
模板代码
//二分查找函数
int binarysearch() {
int l=1; r=n; //初始化左右边界
while(r-l > 1)
{
int mid = (r+l) >> 1; //取中间位置
if(check(mid))
r = mid; //更新右边界为mid--r此处不唯一,根据题意更改(见例题1)
else
l = mid; //否则更新左边界为mid--l此处不唯一,根据题意更改
}
if(check(l)) //如果满足条件--l此处不唯一,根据题意更改
return l; //返回左边界值
else if(check(r) //如果满足条件--r此处不唯一,根据题意更改
return r; //返回有边界值
return -1;//否则返回-1
}
例题实践
分巧克力
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//n块巧克力,k个小朋友
int n, k;
//设定范围
const int def = 1e5 + 10;
int h[def], w[def];
//判别条件
bool check(int x)
{
// 满足条件:正方形,大小相同,切后的个数大于等于k
int sum = 0;
for(int i=0; i<n; i++)
{
//每一块巧克力能够切成边长为x的个数
sum += (h[i]/x)*(w[i]/x);
}
if(sum >= k)
return true;
else
return false;
}
int main(int argc, char** argv) {
cin >> n >> k;
for(int i=0; i<n; i++)
{
cin >> h[i] >> w[i];
}
//定义边界
int l=1, r=1e5;
while(r-l > 1)
{
int mid = (r+l) >> 1;
if(check(mid))
l = mid; //题意是希望边长尽可能大,因此更新左边界,使得边界的最小值更大
else
r = mid;
}
if(check(r)) //执行完成之后,希望边界越大越好,因此先判断右边界
cout << r;
else if(check(l))
cout << l;
return 0;
}