二分算法 原理 及 复杂度 详解

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分算法 原理 及 复杂度 详解相关的知识,希望对你有一定的参考价值。

binary search,常见的翻译有二分查找、二分搜索、折半搜索(这用的名词是 half-interval search)、对数搜索(这里用的名词是 logarithmic search),是一种非常常见并且应用范围也比较广泛的搜索算法。

之前曾看到过一个说法:凡是有序,皆是二分,大概也能说明二分搜索的应用之广泛了。

二分搜索的基础原理

二分可以被用于查找 有序数组 中的某一个特定元素,其工作原理是查找一个 既定值,target数组, arr中点,mid 开始查找,判断 a r r [ m i d ] arr[mid] arr[mid] 的值,存在以下三种情况:

  1. 如果 t a r g e t = a r r [ m i d ] target = arr[mid] target=arr[mid],则找到 target,直接返回 mid
  2. 如果 t a r g e t > a r r [ m i d ] target > arr[mid] target>arr[mid],则代表 target 坐落于 [ 0... m i d ) [0...mid) [0...mid) 区间
  3. 如果 t a r g e t < a r r [ m i d ] target < arr[mid] target<arr[mid],则代表 target 坐落于 ( m i d . . . a r r . l e n g t h ) (mid...arr.length) (mid...arr.length) 区间

这种每迭代一次就会将可选项的数量折半,也是折半搜索名词的来源。

这里也会应用到双指针去确认搜索的区间,关于双指针的知识点细节可以看这里:双指针总结

二分的基础案例

以一个数组作为案例去进行二分查找的步骤,目标值 target 为 1,数组为:

14101217182125
  1. 确认 最大值最小值中点

    这里最大值 a r r . l e n g t h − 1 arr.length - 1 arr.length1,也就是 7,最小值 是数组的起点长度,也就是 0,中点 的计算稍微麻烦一些—— ( 0 + 7 ) ÷ 2 = 3.5 (0+7) \\div 2 = 3.5 (0+7)÷2=3.5,这里会进行向下取整,所以 中点 为 3。

    14101217182125

    对比 target a r r [ m i d ] arr[mid] arr[mid],明显能够看出 1 < 12 1 < 12 1<12,所以在下一个迭代中可以将最大值更新为 m i d − 1 mid - 1 mid1

  2. 更新 最大值最小值中点

    这里最大值 m i d − 1 mid - 1 mid1,也就是 2,最小值 依旧是数组的起点长度,也就是 0,中点 就为 1。

    14101217182125

    对比 target a r r [ m i d ] arr[mid] arr[mid],明显能够看出 1 < 4 1 < 4 1<4,所以在下一个迭代中可以将最大值更新为 m i d − 1 mid - 1 mid1

  3. 更新 最大值最小值中点

    这里最大值 m i d − 1 mid - 1 mid1,也就是 1,最小值 依旧是数组的起点长度,也就是 0,中点 就为 0.5 向下取整,还是 0。

    14101217182125

    鉴于 红+蓝=紫,所以这里将 1 的颜色更新成紫色,表示这既是起点,也是中点。

    继续对比 target a r r [ m i d ] arr[mid] arr[mid],已经找到了对应值,便可以直接返回 mid 作为 index 了。

这就是一个完整的二分搜索的流程。

二分搜索的复杂度

接下来会对时间复杂度和空间复杂度进行分析。

空间复杂度

空间复杂度是很简单的,根据上面的流程可以得知,在整个二分搜索的过程中,只需要额外存储三个变量:最大值最小值中点,也因此,空间复杂度是常量 O ( 1 ) O(1) O(1)

时间复杂度

时间复杂度是 O ( l o g ( n ) ) O(log(n)) O(log(n)),其计算方法会稍微复杂一些,现在就开始从头分析。

已知数组的长度为 n n n,每一次数组的长度都会折半,一直到数组长度为 1:

n , n 2 , n 4 , . . . 1 n, \\frac{n} {2}, \\frac{n} {4}, ... 1 n,2n,4n,...1

所以又可以理解成:

n × ( 1 2 ) k = 1 n \\times (\\frac{1}{2})^k = 1 n×(21)k=1

即, n n n 乘以 1 2 \\frac{1}{2} 21 k k k 次方后的值为 1。这个方程式再简化一下就能得到:

n × 1 2 k = 1 n \\times \\frac{1}{2^k} = 1 n×2k1=1

最后得出:

n = 2 k n = 2^k n=2k

最后应用对数公式,自然能够得出:

k = log ⁡ 2 n k = \\log_2n k=log2n

而在算法中计算空间复杂度和时间复杂度时,是可以忽略掉对数的底的这些常数的,因此时间复杂度也就可以缩写成 l o g ( n ) log(n) log(n)

以上是关于二分算法 原理 及 复杂度 详解的主要内容,如果未能解决你的问题,请参考以下文章

算法二分法 ① ( 二分法基本原理简介 | 二分法与哈希表对比 | 常见算法对应的时间复杂度 )

算法知识常用算法详解丨二分查找法(折半查找)

二分搜索算法详解(Binary Search)

二分搜索算法详解(Binary Search)

对二分算法的理解及结对编程情况

二分查找算法(Python)