对二分法的一些简单总结(4.27~5.3)

这周做了几道关于二分法的题目,对二分法有了基本的了解,我在这里总结一下这几天对二分法的一些理解和想法思路

简单来说,二分法,指的是在答案的区间范围中二分,然后通过二分法每分出一个中间值,就进行判断是否为所求,再根据判断结果逐渐缩小区间范围得到答案。二分法存在的意义就是如此,可以跳过很多没有必要的比较与选择,提高运行效率,而如果想用二分来做,我们一定要明白一个重要条件:二分所要查找的序列一定是单调的!

这里用递归算法举例

#include<bits/stdc++.h>
using namespace std;
int Search(int a[],int z,int y,int key){
    if (z<=y){
        int mid=(z+y)>>1; //这里补充一下,z表示左端,y表示右端,(z+y)>>1的意思就类似于(z+y)/2,为什么要这样写,我在这段代码下面做了补充。
        if (a[mid]==key) 
            return mid;
        else if (a[mid]>key) 
            return Search(a,z,mid-1,key);
        else 
            return Search(a,mid+1,y,key);
    }
    return -1;  //没有找到的话返回-1
}
int main(){
    int a[5]={1,2,7,8,9};
    cout<<binarySearch(a,0,4,7)<<endl;//找到7的序号为2
}

补充:这里用>>1的原因是在运行效率上>>1比/2快!
编译器不会将“/2”优化为“>>1”,因为当被除数为负数时知,/2会向上取整,>>1会向下取整。
即:“/2“为“向零取整”,“>>1”永远向下取整。

后来我从网上又看了很多大佬对STL里面几个函数的说明,分别是lower_bound(),upper_bound()和binary_search()
我就去查了查,然后发现的确是很好用,那这里我就总结一下这几个函数的用法
一、binary_search
函数模板 :binary_search(arr[],arr[]+size , index)。
参数说明:
arr[]:数组首地址。
size:数组元素个数。
index:需要查找的值。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int a[5]={1,2,3,4,5};
    cout<<binary_search(a,a+5,5)<<endl;
    //共五个元素,从中找到5,返回1;若想找6,则返回0,因为数组中没有
}

二、upper_bound()函数
函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置。

int upper_bound(int a[], int size, int key)
{
    int len = size-1;
    int half, middle;
    while(len > 0){
        half = len >> 1;
        middle = first + half;
        if(a[middle] > key)     //中位数大>key,所以在包括last的左半边序列中查找。
            len = half;
        else{
            first = middle + 1;    //中位数<=key,所以在右半边序列中查找。
            len = len - half - 1;
        }
    }
    return first;
}

三、lower_bound()
函数功能: 函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置。

int lower_bound(int a[], int size, int key)
{
    int first = 0, middle;
    int half, len;
    len = size;
    while(len > 0) {
        half = len >> 1;
        middle = first + half;
        if(a[middle] < key) {     
            first = middle + 1;          
            len = len-half-1;       //所以在右边子序列中查找
        }
        else
            len = half;            //所以在左边子序列(包括middle)中查找
    }
    return first;
}

四、总结
总的来说,可以把这三个函数这样写

lower_bound(起始地址,结束地址,要查找的数值) 返回的是数值 第一个等于某元素 的位置。
upper_bound(起始地址,结束地址,要查找的数值) 返回的是数值 第一个大于某个元素 的位置。
binary_search(起始地址,结束地址,要查找的数值) 返回的是 是否存在 这么一个数,是一个bool值。

这里举个例子

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int a[]={1,2,2,2,3,10,22};
	int len=sizeof(a)/sizeof(int);
	printf("lower_bound: %d\n",lower_bound(a,a+len,2)-a);
	printf("upper_bound: %d\n",upper_bound(a,a+len,2)-a);
	printf("binary_search: %d\n",binary_search(a,a+len,2));
	return 0;
}
//结果输出
//lower_bound: 1
//upper_bound: 4
//binary_search: 1

这就是我这周对二分法这一方面的一些理解和总结,具体例题其实大多都相同思路,这里就先不列出了,二分法关键的就是思路理解,剩下的就好做多了(熟练掌握上面STL里面的三个函数真的很重要!很好用!)

本人小白,上文如有不对之处,还请各路大神指出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值