基础算法之二分算法

前言

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

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

整型的二分法

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

看看遍历的简单代码

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

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

还是要多多练习

祝大家开心,睡个好觉

相关推荐
青山木2 分钟前
Hot 100 --- 跳跃游戏 II
java·数据结构·算法·leetcode·贪心算法
Tisfy6 分钟前
LeetCode 3870.统计范围内的逗号:模拟 或 一步计算
数学·算法·leetcode·题解·模拟·遍历
明月_清风15 分钟前
字符串匹配四大经典算法:BF、RK、BM、KMP 到底有什么区别?
后端·算法
明月_清风43 分钟前
多模式字符串匹配:Trie 与 AC 自动机
后端·算法
木井巳1 小时前
【BFS/DFS 解决 FloodFill 算法】衣橱整理
java·算法·leetcode·深度优先·广度优先·宽度优先
热心网友俣先生1 小时前
2026年高教社杯数模国赛A题:五年命题规律与预测
算法·机器学习·数学建模
神明不懂浪漫1 小时前
【第四章】索引——B+树、回表,加快数据库的查找能力的利器
开发语言·数据结构·数据库·经验分享·笔记·b树
LuminousCPP2 小时前
数据结构 - 排序(二):快速排序从错误初版到优化版|双指针划分 + 三数取中 + 小区间插入优化
c语言·数据结构·笔记·算法·排序算法
hansang_IR2 小时前
【题解】P9753 [CSP-S 2023] 消消乐
数据结构·c++·算法
shehuiyuelaiyuehao2 小时前
算法40,模拟运算,替换所有的问号
数据结构·算法·leetcode