#配置deovoice 二分算法理解 | blog of coderdz

二分算法理解

首先,什么是二分查找呢?它是一种高效率查找算法,也称折半查找。为什么说效率高呢?让我们举个例子,A同学随便在心里想一个数,然后B同学来猜这个数,如果按照做普通的方法从1~1000便利找的话,最慢的情况会猜1000次,而如果用二分思想的话,不管他想的是什么数,B都能在10次之内猜到。(首先猜500,除了运气特别好直接猜对外不管A说太大还是太小,B都继续把可行范围缩小一半:如果太大,那么答案在1~499之间,如果太小,则在501~1000之间。只要每次选择可行区间的中点去猜,每次都能把范围缩小一半。由于log2(1000)<10,10次之内一定能猜到)
二分查找的重要条件:要查找的序列一定是单调的
递归算法举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<bits/stdc++.h>
using namespace std;
int binarySearch(int a[],int l,int r,int key){
if (l<=r){
int mid=(l+r)>>1;
if (a[mid]==key) return mid;
else if (a[mid]>key) return binarySearch(a,l,mid-1,key);
else return binarySearch(a,mid+1,r,key);
}
return -1; //没有找到返回-1
}
int main(){
int a[5]={1,3,5,6,7};
cout<<binarySearch(a,0,4,5)<<endl;//找到5的序号为2
}

迭代实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<bits/stdc++.h>
using namespace std;
int binarySearch(int a[],int l,int r,int key){
while(l<=r){
int mid=(l+r)>>1;
if (a[mid]==key) return mid;
else if (a[mid]>key) r=mid-1;
else l=mid+1;
}
return -1; //没有找到返回-1
}
int main(){
int a[5]={1,3,5,6,7};
cout<<binarySearch(a,0,4,7)<<endl;//找到7的序号为4
}

尽管能用递归实现,但一般都不用递归形式的二分写法。
下面介绍一种c++STL函数库里的二分,lower_bound(),upper_bound()binary_search().(STL里的各种数据结构真的是很实用,建议各位花些功夫学好这些)

binary_search():函数模板 :binary_search(arr[], arr[]+size , indx)。
参数说明:arr[]:数组首地址。
size:数组元素个数。
index:需要查找的值。
函数功能: 在数组中以二分法检索的方式查找,若在数组(要求数组元素非递减)中查找到indx元素则返回1,若查找不到则返回值为0。
示例:

1
2
3
4
5
6
7
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[5]={1,3,5,6,7};
cout<<binary_search(a,a+5,6)<<endl;
//找到6,返回1
}

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

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

例:

1
2
3
4
5
6
7
8
9
10
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[10]={1,3,3,5,6,7,7,8,10,12};
cout<<lower_bound(a,a+10,3)-a<<' ';
cout<<upper_bound(a,a+10,3)-a<<' ';
cout<<lower_bound(a,a+10,7)-a<<' ';
cout<<upper_bound(a,a+10,7)-a<<' ';
}
//输出:1 3 5 7

二分原理易懂然而也要在刷题中慢慢提升自己对二分的理解

下面附上一道题吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*问是否有x满足这个等式: 8x^4 + 7x^3 + 2x^2 + 3x + 6 == Y,x属于[0,100],可以为分数
,保留四位小数
*/
#include <iostream>
#include<stdio.h>
using namespace std;
int calculate(int x)
{
return 8*x*x*x*x+7*x*x*x+2*x*x+3*x+6;
}
int main()
{
int y;
double high=100,low=0,mid;
while(cin>>y)
{
while(low-high<1.0e-6) / /循环至high,low近乎相等
{
mid=(high+low)/2;
if(calculate(mid)<y)
low=mid;
else
high=mid;
}
printf("%.4lf\n",high);
}
return 0;
}
谢谢你请我吃苹果!
-------------本文结束感谢您的阅读-------------