二分查找算法小结

二分查找算法小结

#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 x
    xx-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
    
  • */
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值