二分算法
二分 分为 二分查找 和 二分答案
(本篇是二分查找的学习记录)
二分查找
二分查找也称折半查找,顾名思义,就是每次查找去掉不符合条件的一半区间,再到符合条件的另一半区间去查找,直到找到答案或者和答案十分接近。(即区间长度为1)
二分查找的模板
//左查找
while (l < r)
{
int mid = (l + r ) >> 1;
if (mid...) r = mid; //mid与需要找的数的大小关系
else l = mid + 1;
}
//右查找
while (l < r)
{
int mid = (l + r + 1 ) >> 1; //加1是防止区间长度为2时陷入死循环
if (mid...) r = mid - 1; //mid与需要找的数的大小关系
else l = mid ;
}
关于右查找时为什么要加一这个问题困惑了我很久,现在也有些疑惑,下面是我的一些想法
当区间长度为2时,如果判断语句并没有进入使r减小的那一个情况(因为当区间长度为2时,如果mid=(l+r)/2那么mid的值总是偏向左边的),那么会继续执行l=mid,区间长度依旧是2,使循环陷入死循环。如果在做题过程中出现了超时的情况,那么多半是这个问题
下面是一个二分查找的题目
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
int a[100100],b[100100];//定义两个数组,分别储存每个学校的分数线,和每个同学的估分
int main()
{
int n,m,i;
cin>>n>>m;
for(i=1; i<=n; i++)
{
cin>>a[i];
}
for(i=1; i<=m; i++)
{
cin>>b[i];
}
sort(a+1,a+n+1);//把每个学校的分数线从小到大排序,因为是从a[1]开始的
//sort函数是algorithm库下的一个函数,可以用于排序,但是sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变。
int sum=0;//不满度
for(int i=1; i<=m; i++)
{
int l=0,r=n;//定义左边界与右边界
while(l<r)
{
int mid=(l+r) >> 1;
if(a[mid]<=b[i])//如果录取分数线数组中的第mid个元素小于或等于那位同学的分数
{
l=mid+1;
}
else
{
r=mid;
}
}
if(b[i]<=a[1])
{
sum+=a[1]-b[i];
}
else
{
sum+=min(abs(a[l-1]-b[i]),abs(a[l]-b[i]));//加上两个绝对值中最小
//在C++中,abs 函数定义在 <cmath> 或 <math.h> 头文件中,用于取绝对值
}
}
cout<<sum;
return 0;
}
上述解题的代码还有一个测试点无法通过,所以并不完善,还需要再想想
这一篇博客就写到这里吧,是对于学习的一些记录,有诸多不足之处,见谅