二分查找算法小结
#include
#include
using namespace std;
/*二分查找
- a想一个1~1000之间的数,B来猜,a只能回答是或否
- 怎样才能问的问题数最小
- */
/* 写一个函数BinarySearch //(int a[],int size,int p)
- 如果找到返回其坐标,如果找不到返回-1
- */
int BinarySearch (int a[],int size,int p)
{
int left=0;//左侧的端点
int right=size-1;//右侧端点
while(left<=right)
{
int mid=left+(right-left)/2;//查找区间正中的元素的下标
if(p==a[mid])
return mid;
else if(p>a[mid])
left=mid+1;
else
right=mid-1;
}
return -1;
}//复杂度O(log(n))
/*写一个函数LowerBound,在包含size个元素的,从小到大排序的int数组a里查找
*比给定p小的,下标最大的元素。找到返回其下标,找不到则返回-1
- */
int LowerBound(int a[],int size,int p)//复杂度O(log(n))
{
int left=0;//查找区间的左端点
int right=size-1;//右
int Lastpos=-1;//到目前为止找到最优解
while(left<=right)//循环条件
{
int mid=left+(right-left)/2;//查找区间正中元素的下标
if(a[mid]>=p)
{
right=mid-1;
}else{
Lastpos=mid;
left=mid+1;
}
}
return Lastpos;
}
/*二分法求方程的根
*求下面方程的一个跟:f(x)=x3-5x2+10x-80=0;
- 若求出的根是a,则要求出|f(a)<=10^(-6)|
- 因为f(0)<0;f(100)>0;又因为f(x),在0~100内单调递增
- /
//double EPS=1e-6;
//double f(double x)
//{
// return xxx-5xx+10x-80;
//}
//int main()
//{
// double root,x1=0,x2=100,y;
// root=x1+(x2-x1)/2;
// int triedTimes=1;//记录一共尝试了多少次,但对求根来说不是必须的
// y=f(root);
// while(fabs(y)>EPS)
// {
// if(y>0) x2=root;
// else x1=root;
// root=x1+(x2-x1)/2;
// y=f(root);
// triedTimes++;
// }
// printf("%.8f\n",root);
// printf("%d\n",triedTimes);
// return 0;
//}
/*例题1
- 输入n(n<=100,000)个整数,找出其中的两个数,他们之和等于整数m(假设肯定有解)。
- 题中的所有整数能用int表示
- */
//解法 一:用两重循环,枚举所有的取值方法,复杂度是O(n^2)的
//int main()
//{
// int n;
// for (int i = 0; i <n-1 ; ++i) {
// for (int j = i+1; j <n ; ++j) {
// if(a[i]+a[j]==m)
// {
// break;
// }
// }
// }
// //100,000^2=100亿,各种OJ上提交或者参加各种程序设计竞赛,这样的复杂度都会超时
//}
/*解法2:
- 1、将数组排序,复杂度是O(n*log(n))
- 2、对数组中每个元素a[i],在数组中二分查找m-a[i],看能否找到。复杂度log(n)
- ,最坏要查找n-2次,所以查找这部分的复杂度也是O((n-2)*log(n))
- */
/*解法3:
- 1、将数组排序,复杂度是O(n*log(n))
- 2、查找的时候,设置两个变量i和j,i初值是0,j的初值是n-1,看a[i]+a[j],如果
- 大于m,就让j-1,如果小于m,就让i+1;直到a[i]+a[j]=m。
*复杂度也是O((n-2)*log(n)) - */
//void SetIAndJ(int a[],int size,int m)
//{
// int i=0,j=size-1;
// while(a[i]+a[j]!=m)
// {
// if((a[j]+a[i])>m)
// {
// j=j-1;
// }else if((a[j]+a[i])<m)
// {
// i=i+1;
// }else
// {
// break;
// }
// }
//}
/*农夫建造一座很长的牛棚,他包括N个隔间,这些小隔间位置为x0,…,xn-1
- 农夫C头牛每分到一个隔间。牛都希望互相离得远点省的互相打扰。怎样才能使任意
- 两头牛之间最小距离尽可能的大,这个最大的最小距离是多少呢
- */
//解法一,依次尝试,最大距离D从C~0依次找出合适的
/*解法二:
-
先得到排序后的隔间坐标X0,......,XN-1
-
在【L,R】内用二分法尝试“最大最近距离”D=(L+R)/2(L,R初值为1,
-
1,000,000,000/C)
-
若D可行,则记住该D,然后在新【L,R】中继续尝试(L=D+1)
-
若D不可行,则在新【L,R】中继续尝试(R=D-1)
-
//复杂度 log(1,000,000,000/C)*N
- */