[二分法] 在一个非降序列中,查找与给定值相同的元素下标

/*

任务一:北大版 在一个非降序列中,查找与给定值相同的元素下标
写一个 Binarysearch在包含size个元素的、从小到大排序的int数组a里查找元素p,
如果找到,返回元素下标,如果找不到,返回-1. 
*/
#include <iostream>
using namespace std;
int Binarysearch(int a[],int size,int p) {
    int L=0;
    int R=size-1;
    while(L<=R) {//如果区间不为空就继续查找 
        int mid=L+(R-L)/2;//取查找区间正中元素的下标 
        //cout<<L<<" "<<mid<<" "<<R<<endl;
        if(p==a[mid]) return mid;
        else if(p>a[mid]) L=mid+1;//设置新的查找区间的左端点 
        else R=mid-1;//设置新的查找区间的右端点
    }
    return -1;
}
int main() {
    int a[20]= {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
    int mid;
    cout<<Binarysearch(a,20,18)<<endl;//第一个参数 指向数组头的指针 第二个参数 数组大小 第三个参数 要查找的值 
    return 0;
}

/*

任务2:北大写一个函数 LowerBound,在包含size个元素的从小到大排序int数组a里查找比给定整数p小的,下标最大元素。找到则返回其下标 找不到返回-1

思考查找比给定整数p大的,下标最小元素,怎么改?

*/

#include <iostream>

using namespace std;

int LowerBound(int a[],int size,int p) {

    int L=0;

    int R=size-1;

    int lastPos=-1;//目前为止 找到的最优解

    while(L<=R) {//如果区间不为空就继续查找

        int mid=L+(R-L)/2;//取查找区间正中元素的下标

        //cout<<L<<" "<<mid<<" "<<R<<endl;

        if(a[mid]>p) R=mid-1;//设置新的查找区间的右端点

        else {

            lastPos=mid;

            L=mid+1;//

        }

    }

    return lastPos;

}

int main() {

    int a[20]= {0,1,2,3,4,5,6,7,8,9,10,14,15,16,17,18,29,30,41,52};

    cout<<a[LowerBound(a,20,50)]<<endl;

    return 0;

}

任务3: 原创版

/*

写一个函数,在包含size个元素的从小到大排序int数组a里

查找和整数p最接近的元素

*/

#include <iostream>

using namespace std;

int LowerBound(int a[],int size,int p) {

    int L=0;

    int R=size-1;

    while(R-L>1) {//注意此处出口  最后找出L-R=1的两个值

        int mid=L+(R-L)/2;//取查找区间正中元素的下标

        if(a[mid]>p) R=mid;//此处不能写成mid-1

        else if(a[mid]<p){

            L=mid;

        }else return mid;

    }

    cout<<L<<" "<<R<<endl;

    return (p-a[L])<(a[R]-p)?L:R;

}

int main() {

    int a[20]= {0,1,2,3,4,5,6,7,8,9,10,14,15,16,17,21,29,30,41,52};

    cout<<a[LowerBound(a,20,18)]<<endl;

    return 0;

}

改进lower

/*

写一个函数 LowerBound,在包含size个元素的从小到大排序int数组a里查找比给定整数p小的,下标最大元素。返回其下标

*/

#include <iostream>

using namespace std;

int LowerBound(int a[],int size,int p) {

    int L=0;

    int R=size-1;

    while(R-L>1) {//注意此处出口  最后找出L-R=1的两个值

        int mid=L+(R-L)/2;//取查找区间正中元素的下标

        if(a[mid]>p) R=mid;//此处不能写成mid-1

        else if(a[mid]<p){

            L=mid;

        }else return mid;

    }

    cout<<L<<" "<<R<<endl;

    return L;

}

int main() {

    int a[20]= {0,1,2,3,4,5,6,7,8,9,10,14,15,16,17,21,29,30,41,52};

    cout<<a[LowerBound(a,20,18)]<<endl;

    return 0;

}

改进upper呢?

 

任务4:algorithm里 lower 和upper 含义不一样

/*

lower_bound(r[x].begin(),r[x].end(),l)

upper_bound(r[x].begin(),r[x].end(),R)

函数lower_bound()返回第一个大于等于x的数的地址

函数upper_bound()返回第一个大于x的数的地址

*/

#include <iostream>

#include <algorithm>

using namespace std;

int main() {

    int a[20]= {0,1,2,2,3,5,6,7,8,9,10,14,15,16,17,21,29,29,29,52};

    cout<<*lower_bound(a,a+20,2)<<"-下标为"<<lower_bound(a,a+20,2)-a<<endl;

    cout<<*upper_bound(a,a+20,2)<<"-下标为"<<upper_bound(a,a+20,2)-a<<endl;

    return 0;

}

后面是转载的 QAQ https://blog.csdn.net/tiao738760029/article/details/79776445

binary_search() :

  • 查找指定值,存在返回下标,否则返回假
  • idx = binary_search(A,A+n,want);

lower_bound() :

  • 返回一个迭代器,指向第一个 大于等于 指定值得元素
  • 找不到时返回末尾迭代器,可以计算距离如果大于最大下标则不存在
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int A[14]={1,1,2,2,2,4,5,5,6,8,8,8,10,15};
    int * pos;
    int idx;
    pos = lower_bound(A,A+14,3);//查找第一个大于等于3的元素,返回迭代器
    idx = distance(A,pos);//计算连个迭代器距离,即返回目标的下标
    cout<<"A["<<idx<<"]="<<*pos<<endl;
    //A[5]=4;
}
  •  

upper_bound() :

  • 查找第一个大于指定值得元素,用法同上
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章