二分法查找一定比遍历查找更快吗?

本人大概五年前作为初学者接触过时间复杂度的相关概念,但是实际写代码的时候,可能因为领域不同,一直都没有碰到需要设计时间复杂度的问题,都只是需要实现功能就行了,所以一直以来,脑海中的印象仅限于二分法这个词,只记得二分法查找比普通方法更好(你是不是也是这样?)。

近期本人碰到了大规模计算的实际问题,需要考虑算法性能,才切实体会到了合理的时间复杂度确实能极大降低计算时间。

这篇博客偏向于深入理解,帮助初学者避开一些理解误区,不提供代码(因为网上代码太多了)。

那么,回到问题,二分法一定优于遍历吗?

首先,二分法依赖于顺序存储结构,原因在于二分法的执行过程中需要不断通过索引取值,取出的值将作为要查找的值的比较对象

其次,典型的实际问题通常是,给定一个数组(数组是无序的),需要在数组中查找某个值

如果用普通方法,那就遍历一遍。如果用二分法,那就先排序再查找,较好的排序方法的时间复杂度是O(nlogn),查找的时间复杂度是O(logn)(关于两项时间复杂度,这里不展开说明)。

注意,以下的计算并不是严格的数学推导,只是便于理解两种方法的区别

假设在n个数中查找一个数,那么,两种方法的时间复杂度分别是

普通方法:遍历O(n)

二分法:排序O(nlogn) + 查找O(logn)

假设这样查找的次数为x次,而且假设x次的时间复杂度可以累计,那么,两种方法累计的时间复杂度分别是

普通方法:xO(n)

二分法:O(nlogn) + xO(logn)

两种方法累计的计算耗时可以近似为

普通方法:xn

二分法:nlogn + xlogn

这时,对于特定的n,将查找次数x视为自变量,计算耗时视为函数值,则普通方法的斜率为n,二分法的斜率为logn,显然普通方法的斜率大于二分法的斜率。

当x=1时,普通方法耗时n < 二分法耗时nlogn + logn

当x=n时,普通方法耗时n*n > 二分法耗时nlogn + nlogn

可以理解,当x等于1~n之间的某个数x’时,如果查找次数再增大,那么二分法才会体现出计算耗时更短的优势

也就是说,如果查找次数较多(也就是频繁查找),更适合用二分法(先排序一遍,再查找多遍),如果只查找一次,那还不如直接遍历一遍,毕竟二分法的排序耗时就摆在那里。如果加强约束条件,数组自身就是排序好的,那么二分法省去了排序的时间,基本上可以认为二分法比普通方法耗时更短了

另外,从实际运用角度来说,问题规模需要达到一定数量,才能体现出二分法的优势。

这里做一个测试:

设定数组的长度为val,数组存的值依次为0~val-1,而在数组中,要查找的数值为val-9。例如,val=10^2=100时,数组存的值为0~99,要查找的数值为91。设定查找次数为100次,记录val从10^2~10^8的情况下,两种方法查找的耗时,单位为s。(代码由c++编写,而且这里忽略二分法排序的耗时,数组就是排序好的

val

10^2

10^3

10^4

10^5

10^6

10^7

10^8

普通方法

0.000

0.000

0.001

0.008

0.086

0.894

8.973

二分法

0.000

0.000

0.000

0.000

0.000

0.000

0.000

可以看出,在val为10^2~10^6时,两种方法几乎体现不出计算时间的差别,当val=10^8时,才显现出明显的差别。

所以,对于小规模问题,普通方法和二分法,都能快速运行,当问题规模增大到一定程度,二分法才会体现出计算耗时更短的优势,才更适合用二分法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值