基础算法之二分算法

前言

本次博客,将要介绍二分算法的基本原理以及如何使用,深入浅出

二分可以针对整型以及浮点型接下来对其讲解希望对小白有所帮助吧

整型的二分法

一般要在一个数组中猜出一个数是否存在我们可以遍历一遍整个数组,判断是否存在,

看看遍历的简单代码

复制代码
#include<stdio.h>
int main()
{
int arr[]={5,6,8,1,2,3,10,20,50};
int find=1;
for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
if(arr[i]==find)
{
printf("找到了\n");
break;
}
}
return 0;
}

但是如果这个数组的数是有序的,从大到小或从小到大的话

比如 1 2 3 4 5 6 7 8 9 10

我们可以从中间的数开始与要查找的数相比

如果中间的数大于查找的数 那么要查找的数在整个数组的左边,那么右边的数可以摒弃,右边界往左一半

如果中间的数小于查找的数 那么查找的数在整个数组的右边,那么左边的数可以摒弃,左边界往右一半

最终 左边和右边会相等或者是左边会大于右边此时循环结束

当然有两种情况是因为二分的范围不同,按照数学的集合的概念可以是 左闭右闭

也可以是左闭右开 以及左开右开

闭就是取得到,开就是取不到

前两种用的更多,最后一种比较少

我们现在举一个例子,模拟一下在一个有序数组里中查找数的过程,简单的画个图以便理解

下面的图是左闭右闭为例

接下来还是看代码吧

先敲个左闭右闭

复制代码
//左闭右闭
int main()
{
	int arr[10] = { 5,9,10,20,30,99,123,145,199,200 };
	int find;
	printf("请输入要找到的数");
	scanf("%d", &find);
	int left = 0;
	int right = sizeof(arr) / sizeof(arr[0])-1;
	//这里必须要写等于,不写会错,很多人在这里会犯错
	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (arr[mid] > find)//因为mid不等于find所以-1缩小范围
			right = mid - 1;
		else if (arr[mid] < find)
			left = mid + 1;
		else
		{
			printf("找到了该数的下标为%d", mid);
			break;//这里要写break不然是死循环
		}
	}
	if (left > right)
	printf("没找到\n");
	return 0;
}

注意左闭右闭是要取到left==right的值比如 如果循环中没有等号

当范围为1,1且要查找的数为 1时,此时就会出现找不到的bug

这个很重要

接下来可以写一写左闭右开,其实也差不多

看看

复制代码
//左闭右开
int main()
{
	int arr[] = { 20,36,55,69,100,300,500,1000,1002,1225 };
	int left = 0;
	int right = sizeof(arr) / sizeof(arr[0]);//这里取不到
	int find;
	printf("请输入要查找的数");
	scanf("%d", &find);
	while (left < right)//由于右边是取不到的所以不加等号
	{
		int mid = (left + right) / 2;
		if (arr[mid] > find)
			right = mid;//mid所指向的值不等于find,但是右边是开取不到的所以不减1
		else if (arr[mid] < find)
			left = mid + 1;//左边取得到 arr[mid]可以排除在外
		else
		{
			printf("找到了该数的下标为%d", mid);
			break;//不写可能死循环
		}
	}
	if (left >= right)
		printf("找不到\n");
	return 0;
}

这样我们就解决了,很多初学者不知道什么时候加一什么时候减一

非常nice

整型的二分到此就结束了

希望大家注意

1 二分是要有序的

2 二分可按区间判断左右边结束条件 以及调整方法

3找到后记得跳出循环

4注意它的时间复杂是log2n

浮点型的二分

浮点型的数据,在内存中往往是不精确的,那么为了解决这个问题,我们可以通过夹逼的方式

来处理问题

那么执行次数越多精确值越大,如果执行100次二分 那么就是2的100次方分之一的精确度

非常精确

此时的left right 代表的是这个数的范围,一直二分,每次将范围缩小二分之一,可以吧

比如

求一个数的立方根,并且精确到第6位小数

加设这个数的立方根的范围为-100~100

我们本次以此为例

通过浮点数的二分来解决问题,在此之前可以画图让大家了解

看代码吧

复制代码
int main()
{
	double input;
	scanf("%lf", &input);
	double right=100;
	double left=-100;
	double ans = 0;
	for (int i = 0; i < 100; i++)
	{
		double mid = (right + left)/2;
		if (mid * mid * mid <= input)
			left = mid;
		else
			right = mid;
	}
	ans = left;
	printf("%lf", ans);
	return 0;
}

浮点数的精确除了直接使用for循环直接执行100外,也可以用right-left<精确度

比如保留6为小数就可以 right-left<1e-6

至此二分法的基础也算是讲解完了,这个算法还算是比较简单

还是要多多练习

祝大家开心,睡个好觉

相关推荐
计算机安禾几秒前
【算法分析与设计】第21篇:回溯法的状态空间树与剪枝函数设计
大数据·人工智能·算法·机器学习·数据挖掘·剪枝
磊 子2 分钟前
STL之set以及set和map区别
开发语言·c++·算法
Promise微笑11 分钟前
算法突围:“双核四驱”理论下的“官网”AI引用概率提升指南
人工智能·算法·chatgpt
KaMeidebaby17 分钟前
卡梅德生物技术快报|免疫共沉淀 - Co-IP 实验在转录因子 ATF3/Smad4 蛋白互作研究中的应用实例解析
网络·人工智能·网络协议·tcp/ip·其他·算法·新浪微博
wayz1122 分钟前
20260530 软件ETF(159852)量化分析
算法·金融·数据分析·量化交易
通信小呆呆37 分钟前
Hankel结构及其快速算法详解
线性代数·算法·机器学习
四代水门37 分钟前
服务端倒带(Server-Side Rewind)命中判定系统
java·前端·算法
吃好睡好便好38 分钟前
矩阵的左除和右除
人工智能·学习·线性代数·算法·矩阵
南境十里·墨染春水41 分钟前
数据结构 ——BST 树
数据结构
江屿风44 分钟前
C++图的基本概念流食般投喂-竞赛编
开发语言·数据结构·c++·笔记·算法·图论