今天无聊,决定在CSDN上发布我的第一篇文章,与大家分享一下二分查找算法。二分查找是一种高效的在有序数组中查找特定元素的算法,其核心思想是通过反复将查找范围减半来快速定位目标元素。
二分查找的基本原理
二分查找的基本思想非常简单。每次查找时,将数组的中间元素与目标值进行比较:
通过这种反复减半的方式,二分查找能够在对数时间复杂度内完成查找。
时间复杂度分析
在二分查找中,每次查找都会将查找范围减半。因此,最坏情况下的时间复杂度是 O(log2n),其中 n 是数组的元素个数。
以 1 亿(即 108108)个数字为例:
log2(108)=log10(108)log10(2)log2(108)=log10(2)log10(108)
计算得到:
log10(108)=8log10(108)=8
log10(2)≈0.3010log10(2)≈0.3010
log2(108)≈80.3010≈26.58log2(108)≈0.30108≈26.58
由于查找次数必须是整数,因此最多需要进行 27 次查找。
二分查找的实现
接下来,我们通过一个具体的例子来介绍二分查找的实现。我们先设定一个目标:查找值为2的数字一共出现了多少次,我们先从简单的开始,查找值为2的数字第一次出现的位置。
初始时,我们令L = -1,R = array.length,L为左边界,R为右边界。
怎么二分呢,就是找分界线,那么2第一次出现的位置分界线应该是什么呢,那么就是从那个位置开始都是>=2的,通过L,R枚举中间值Mid,如果arr[Mid]>=find就让R右移,否则就是L左移,那么最后分界线的右边,也就是R就是2第一次出现的位置。
实现代码
#include
using namespace std;
int arr[] = {1,1,2,2,2,3,3,4};
int main(){
int len = sizeof arr / sizeof arr[0];
int find = 2;
int L = -1,R = len;
while(L+1> 1;// (L+R)/2
if(arr[Mid]>=find) {
cout<<"中间值大于等于要查找的值,右边界左移\n";
//printf("间值大于等于要查找的值,右边界左移\n");
R = Mid;
}
else{
cout<<"中间值小于要查找的值,左边界右移\n";
//printf("中间值小于要查找的值,左边界右移\n");
L = Mid;
}
}
cout<<"左边界:"<
执行结果
接下来我们查找2最后出现的位置,那么分界线就是从那个位置往前都是<=2的,同样的道理,通过L,R枚举中间值Mid,如果arr[Mid]<=find就让L右移,否则就是R左移,那么最后分界线的左边,也就是L就是2最后一次出现的位置。
实现代码
#include
using namespace std;
int arr[] = {1,1,2,2,2,3,3,4};
int main(){
int len = sizeof arr / sizeof arr[0];
int find = 2;
int L = -1,R = len;
while(L+1> 1;// (L+R)/2
if(arr[Mid]>=find) {
cout<<"中间值大于等于要查找的值,右边界左移\n";
//printf("间值大于等于要查找的值,右边界左移\n");
R = Mid;
}
else{
cout<<"中间值小于要查找的值,左边界右移\n";
//printf("中间值小于要查找的值,左边界右移\n");
L = Mid;
}
}
cout<<"左边界:"<> 1;// (L+R)/2
if(arr[Mid]<=find) {
cout<<"中间值小于等于要查找的值,左边界右移\n";
//printf("中间值小于等于要查找的值,左边界右移\n");
L = Mid;
}
else{
cout<<"中间值大于要查找的值,右边界左移\n";
//printf("中中间值大于要查找的值,右边界左移\n");
R = Mid;
}
}
cout<<"左边界:"<
执行结果
那么我们要实现的目标:查找2出现的次数,就是(2最后出现的位置)-(2第一次出现的位置)+1
实现代码
#include
using namespace std;
int arr[] = {1,1,2,2,2,3,3,4};
int main(){
int len = sizeof arr / sizeof arr[0];
int find = 2;
int L = -1,R = len;
while(L+1> 1;// (L+R)/2
if(arr[Mid]>=find) {
cout<<"中间值大于等于要查找的值,右边界左移\n";
//printf("间值大于等于要查找的值,右边界左移\n");
R = Mid;
}
else{
cout<<"中间值小于要查找的值,左边界右移\n";
//printf("中间值小于要查找的值,左边界右移\n");
L = Mid;
}
}
cout<<"左边界:"<> 1;// (L+R)/2
if(arr[Mid]<=find) {
cout<<"中间值小于等于要查找的值,左边界右移\n";
//printf("中间值小于等于要查找的值,左边界右移\n");
L = Mid;
}
else{
cout<<"中间值大于要查找的值,右边界左移\n";
//printf("中中间值大于要查找的值,右边界左移\n");
R = Mid;
}
}
cout<<"左边界:"<
执行结果
大概就是这样,但是省略一些,比如说要查找的数字不存在的情况,如果是查找第一次出现就用R判断(if(arr[R]==find)),如果是查找最后一次出现就用L判断(if(arr[L]==find))好了,还有四分钟宿舍关门!!!