二分查找递归与非递归的时间比较_二分算法—一尺之捶,日取其半,log2n世竭...

01a17b49eec37f5656b0ea0020dad978.png

伟大的思想家庄子曾说过:「一尺之捶,日取其半,万世不竭」。这在纯数学理论上是成立的,我们可以在想象中将一尺无限分割为 1/2^n 尺。在实际生活中,我们却不可能将其无限细分,现在已发现的最小粒子单元是夸克,也就是说我们将「一尺之捶」最多分到一夸克便不可再分。限制我们继续细分的便是人类当前认知 有界。在算法世界,也有这样一种算法,它将一种条件一分为二,二分为四,达到可分的边界时停止。这就是二分算法。

来看一张动图了解一下:

8f83b24ed9325378e9582fdd72d58414.gif

适用情境

二分算法适用范围很广,只要满足以下两个条件,就能使用二分算法。

  • 单调
  • 有界

单调的作用是让我们可以找到一个判断条件,每次分割后根据此判断条件缩小搜索范围;有界的作用是限制分割次数,在代码中体现就是根据边界终止循环。

我们在力扣题库中点击「二分查找」标签,显示如下:

f6fc3eac138cbdcbed95e77f35d0111d.png

粗略浏览可以发现,二分查找的题目中很多都带有「有序」、「排序」字样,这是一个很明显的单调条件,数组的长度是有限的,这是一个隐藏的有界条件。

固定写法

二分法有固定的写法:

kotlin 实现

b83a3dec21d4973fa547b7733c4fe7c8.png

递归实现与非递归实现

例题:力扣 35. 搜索插入位置 力扣(点击链接查看题目)

这是一道典型的二分题目。根据题目描述我们可以分析出:

  • 因为数组是有序的,所以 target 越大,答案越大,答案和 target 单调递增的关系
  • 答案是有界的,在 [0, nums.size] 之间

根据二分法的固定写法,我们可以很快写出答案:

kotlin 实现

0c070fafdfec25a6e3b113e3679f37c2.png

使用递归实现,需要将左边界和右边界作为参数传给递归函数,代码如下:

kotlin 实现

222c98d9dc31fb4866077e7e61a1c76c.png

时间复杂度和空间复杂度分析

二分算法每次把搜索区域减少一半,所以时间复杂度是 O(log2n) 级的;

由于辅助变量是固定的,空间复杂度是 O(1).

后记

一日,你到图书馆阅读书籍后,带了 n 本书出图书馆。这时,图书馆的报警器响起了「滴滴滴」的警报声!

正在埋头钻研《算法导论》的图书馆阿姨闻声走过来,说道:「呔!哪路小贼在此放肆,还不快将那本偷的书放下」。

于是你放下所有书,正准备一本本的试是哪一本书没有办理借阅手续,阿姨鄙夷的看你一眼,说道:「真笨,二分算法都不会。」

只见阿姨先将一半的书通过报警器,报警器响起了滴滴声。阿姨将这一半书再分一半,再次通过报警器,又响起了滴滴声……在 log2n 次比较之后,阿姨很快找到了报警的那一本书。阿姨得意地对你炫耀说:「看,这样多高效!」

然后,你在阿姨的带领下办理了那一本书的借阅手续,利用阿姨会二分算法,成功带走了剩余 n-1 本也没有办理借阅手续的书!

本文作者:Alpinist Wang

声明:本文归 “力扣” 版权所有,如需转载请联系。

文中部分图片来源于网络,为非商业用途使用,如有侵权联系删除。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值