这周做了几道关于二分法的题目,对二分法有了基本的了解,我在这里总结一下这几天对二分法的一些理解和想法思路
简单来说,二分法,指的是在答案的区间范围中二分,然后通过二分法每分出一个中间值,就进行判断是否为所求,再根据判断结果逐渐缩小区间范围得到答案。二分法存在的意义就是如此,可以跳过很多没有必要的比较与选择,提高运行效率,而如果想用二分来做,我们一定要明白一个重要条件:二分所要查找的序列一定是单调的!
这里用递归算法举例
#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里面的三个函数真的很重要!很好用!)
本人小白,上文如有不对之处,还请各路大神指出!