zoukankan      html  css  js  c++  java
  • 二分思想

    #include<cstdio>
    using namespace std;
    //二分查找
    int bsrch(int l,int r,int k,int a[])
    {
        int mid;
        while(l<=r){
            mid=(l+r)/2;
            if(a[mid]>k)r=mid-1;
            else if(a[mid]==k)return mid;
            else l=mid+1;
        }
        return -1;
    }
    //有序区间下界
    //第一个大于等于k的元素的位置
    int lowerBound(int l,int r,int k,int a[]) { while(l<r){ int mid=(l+r)/2; if(a[mid]>=k)r=mid;//进入左子区间[l,mid] else l=mid+1;//进入右子区间[mid+1,r] } return l; } //有序区间上界
    //第一个大于k的元素位置
    int upperBound(int l,int r,int k,int a[]) { while(l<r){ int mid=(l+r)/2; if(a[mid]>k)r=mid; else l=mid+1; } return l; } int main() { int a[]={1,2,3,3,3,3,3,4,5,6,7}; int l=0,r=10; int k=3; printf("%d ",bsrch(0,10,k,a)); printf("%d ",lowerBound(0,10,k,a)); printf("%d ",upperBound(0,10,k,a)); while(1); }

    这是三段非常相似的代码。二分查找比较明确,难懂的是下面的两段代码。大体的思路沿袭二分的想法,区别就在于搜索左右子区间的条件不同。

    可以注意到一个特点,lowerBound返回的下标对应的值一定大于等于k,循环结束的条件是l==r,所以满足条件,upperBound类似。

    写成递归形式可能更容易理解,下面就是lowerBound的递归形式

    int lowerBound_r(int l,int r,int k,int a[])
    {
        if(l==r)return l;
        int mid=(l+r)/2;
        if(a[mid]>=k)return lowerBound_r(l,mid,k,a);
        else return lowerBound_r(mid+1,r,k,a);
    }

    从递归看返回的就是最左边的大于等于k的值

    类似得出upperBound的递归形式

    int upperBound_r(int l,int r,int k,int a[])
    {
        if(l==r)return l;
        int mid=(l+r)/2;
        if(a[mid]>k)return upperBound_r(l,mid,k,a);
        else return upperBound_r(mid+1,r,k,a);
    }

    返回最左边的大于k的位置

  • 相关阅读:
    The 2019 ICPC Asia Shanghai Regional Contest H Tree Partition k、Color Graph
    回溯法、子集树、排列树、满m叉树
    顺时针打印矩阵
    单调递增的数字
    nodejs
    nodejs + express + mangodb 项目搭建
    nodejs + express 项目初始化
    星星评分功能(带小数点的那种,5颗星,10分制)
    easyui 增加删除toolbar 显示异常问题
    sql 外键级联,触发器防删
  • 原文地址:https://www.cnblogs.com/MalcolmMeng/p/8452038.html
Copyright © 2011-2022 走看看