基础算法之二分算法

前言

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

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

整型的二分法

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

看看遍历的简单代码

复制代码
#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

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

还是要多多练习

祝大家开心,睡个好觉

相关推荐
Coder-magician3 分钟前
图论总结篇
算法·图论
有同事要进步9 分钟前
Leecode第68题:x的平方根
java·数据结构·算法
吹什么轩16 分钟前
linux系统复习:进程优先级与O(1)调度
java·linux·算法
开开心心就好27 分钟前
安卓PDF处理工具,免费无广告零弹窗
android·服务器·开发语言·算法·pdf·ocr
Pniubi28 分钟前
HashMap扩容全流程
java·开发语言·数据结构
zyl76516 小时前
FlashAttention 详解:从 GPU 硬件、普通 Attention 到分块计算与 Online Softmax
算法
爱读书的小胖20 小时前
LeetCode 122:买卖股票的最佳时机 II(C)解题分析
算法
结局无敌20 小时前
React Native for OpenHarmony 实战:三方库 react-native-modal-dialog 的鸿蒙化适配指南
深度学习·算法·react native·react.js·harmonyos
OPEN-F21 小时前
ROS2系列教程:上位机建图与导航(原理综合)
算法·机器人
weixin_3077791321 小时前
C++代码实现MATLAB中的fitrtree函数功能
开发语言·c++·算法·matlab