算法篇——二分查找

二分查找:从理论到实践

前言

今天无聊,决定在CSDN上发布我的第一篇文章,与大家分享一下二分查找算法。二分查找是一种高效的在有序数组中查找特定元素的算法,其核心思想是通过反复将查找范围减半来快速定位目标元素。

二分查找的基本原理

二分查找的基本思想非常简单。每次查找时,将数组的中间元素与目标值进行比较:

  • 如果中间元素等于目标值,则查找成功。
  • 如果中间元素小于目标值,则目标值只可能在右半部分,查找范围缩小为右半部分。
  • 如果中间元素大于目标值,则目标值只可能在左半部分,查找范围缩小为左半部分。

通过这种反复减半的方式,二分查找能够在对数时间复杂度内完成查找。

时间复杂度分析

在二分查找中,每次查找都会将查找范围减半。因此,最坏情况下的时间复杂度是 O(log2​n),其中 n 是数组的元素个数。

 1 亿(即 108108)个数字为例:

log⁡2(108)=log⁡10(108)log⁡10(2)log2​(108)=log10​(2)log10​(108)​

计算得到:

log⁡10(108)=8log10​(108)=8

log⁡10(2)≈0.3010log10​(2)≈0.3010

log⁡2(108)≈80.3010≈26.58log2​(108)≈0.30108​≈26.58

由于查找次数必须是整数,因此最多需要进行 27 次查找

二分查找的实现

接下来,我们通过一个具体的例子来介绍二分查找的实现。我们先设定一个目标:查找值为2的数字一共出现了多少次,我们先从简单的开始,查找值为2的数字第一次出现的位置。

         算法篇——二分查找_第1张图片

初始时,我们L = -1,R  = array.length,L为左边界,R为右边界。

怎么二分呢,就是找分界线,那么2第一次出现的位置分界线应该是什么呢,那么就是从那个位置开始都是>=2的,通过L,R枚举中间值Mid,如果arr[Mid]>=find就让R右移否则就是L左移,那么最后分界线的右边,也就是R就是2第一次出现的位置。

算法篇——二分查找_第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<<"左边界:"<

 执行结果

算法篇——二分查找_第3张图片

接下来我们查找2最后出现的位置,那么分界线就是从那个位置往前都是<=2的同样的道理,通过L,R枚举中间值Mid,如果arr[Mid]<=find就让L右移否则就是R左移那么最后分界线的左边,也就是L就是2最后一次出现的位置。

算法篇——二分查找_第4张图片

实现代码

#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<<"左边界:"<

执行结果

算法篇——二分查找_第5张图片

那么我们要实现的目标:查找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<<"左边界:"<

执行结果

算法篇——二分查找_第6张图片

大概就是这样,但是省略一些,比如说要查找的数字不存在的情况,如果是查找第一次出现就用R判断(if(arr[R]==find)),如果是查找最后一次出现就用L判断(if(arr[L]==find))好了,还有四分钟宿舍关门!!!

你可能感兴趣的:(算法,算法)