• 八、二分查找


     二分查找常用与一个有序序列或一个具有单调性问题中。

    8.1 编程思路:

    1. 设有一数组 (a[n]) ,数组中的元素按值从小到大排列有序。用变量 (low, high)(mid) 分别指示待查元素所在区间的下界、上界和中间位置。初始时,(low=0,high=n-1) ,查找 (x) 是否在序列中。
    2. (mid = (low+ high) /2) 。(建议写成 (mid = low+(high-low)/2),可以避免数过大越界)
    3. 比较给定值 (x)(a[mid]) 值的大小:
      • (a[mid] == x) ,则查找成功,结束查找;
      • (a[mid]> x) ,则表明给定值 (x) 只可能在区间 (low sim mid-1) 内,修改检索范围。令 (high=mid-1)(low) 值保持不变;
      • (a[mid]< x) ,则表明给定值 (x) 只可能在区间 (mid+1sim high) 内,修改检索范围。令 (low=mid+1,high) 值保持不变。
    4. 比较当前变量 (low)(high) 的值,若 (low≤high) ,重复执行第1、2两步,若 (low>high) ,表明数组中不存在待查找的元素,查找失败。
    • eg : a[]={10,14,21,38,45,47,53,81,87,99},查找47

    8.2 代码实现:

    int binarysearch(int a[],int num,int x){
        int left=0,right=num-1;//查找区间[left,right]
        while(left<=right){//跳出循环时left=right+1
            int mid = left+(right-left)/2;//避免(left+right)溢出
            if(a[mid] == x)return mid;
            if(a[mid] < x)
                left = mid + 1;
            else
                right = mid - 1;
        }
        return -1;//执行到这一步说明个序列中不存在x
    }
    
    • 上面算法在查找一个数是否存在很高效,但存在局限性。
    • 比如说给你有序数组$a[]={1,2,2,2,3}, x=2$,此算法返回的索引是 $2$,没错。但是如果我想得到 (x) 的左侧边界,即索引 $1$,或者我想得到 (x) 的右侧边界,即索引 $3$ ,那我们该如何处理。

    8.2.1 左侧边界代码实现

    int binarysearch(int a[],int num,int x){//查找数组a,[0,num-1]中比x小的个数
        int left=0,right=num;//查找区间[left,right)
        while(left<right){//跳出循环时left=right
            int mid = left+(right-left)/2;//避免(left+right)溢出
            if(a[mid] >= x) //求左边界我们尽量遇到==x的时候右边界往左移
                right = mid;//注意是左闭右开区间右区间缩小不需要减一
            else
                left = mid + 1;//新的区间不包含a[mid]
        }
        return left;//跳出循环时left指向第一个x的位置
    }
    

    8.2.2 右侧边界代码实现

    int binarysearch(int a[],int l,int r,int x){//查找数组a,[l,r]中元素x的位置
        int left=0,right=num;//查找区间[left,right)
        while(left<right){//跳出循环时left=right
            int mid = left+(right-left)/2;//避免(left+right)溢出
            if(a[mid] <= x) //求右边界我们尽量遇到==x的时候左边界往右移
                left = mid+1;//注意是左闭右开区间
            else
                right = mid;//新的区间不包含a[mid]
        }
        return left-1;//注意left要减一,跳出循环时left指向最右x的下一个位置
    }
    
  • 相关阅读:
    eclipse异常关闭,无法启动tomcat解决办法
    VM下,装centos7系统,配置nginx的问题
    用php代码统计数据库中符合条件的行数
    css中的相对定位与绝对定位的区别
    URL地址理解
    开机直接显示用户被锁定点一下就黑屏
    css3 三个属性:-webkit-tap-highlight-color,-webkit-touch-callout,-webkit-user-select
    jquery.flipster.js 3D旋转木马效果
    css3 position:sticky 固定导航平滑过渡
    iframe跨域获取父页面url
  • 原文地址:https://www.cnblogs.com/hbhszxyb/p/12232132.html
Copyright © 2020-2023  润新知