二分算法 原理 及 复杂度 详解
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] 的值,存在以下三种情况:
- 如果 t a r g e t = a r r [ m i d ] target = arr[mid] target=arr[mid],则找到 target,直接返回 mid
- 如果 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) 区间
- 如果 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,数组为:
1 | 4 | 10 | 12 | 17 | 18 | 21 | 25 |
-
确认 最大值 ,最小值 和 中点
这里最大值 是 a r r . l e n g t h − 1 arr.length - 1 arr.length−1,也就是 7,最小值 是数组的起点长度,也就是 0,中点 的计算稍微麻烦一些—— ( 0 + 7 ) ÷ 2 = 3.5 (0+7) \\div 2 = 3.5 (0+7)÷2=3.5,这里会进行向下取整,所以 中点 为 3。
1 4 10 12 17 18 21 25 对比 target 和 a r r [ m i d ] arr[mid] arr[mid],明显能够看出 1 < 12 1 < 12 1<12,所以在下一个迭代中可以将最大值更新为 m i d − 1 mid - 1 mid−1。
-
更新 最大值 ,最小值 和 中点
这里最大值 是 m i d − 1 mid - 1 mid−1,也就是 2,最小值 依旧是数组的起点长度,也就是 0,中点 就为 1。
1 4 10 12 17 18 21 25 对比 target 和 a r r [ m i d ] arr[mid] arr[mid],明显能够看出 1 < 4 1 < 4 1<4,所以在下一个迭代中可以将最大值更新为 m i d − 1 mid - 1 mid−1。
-
更新 最大值 ,最小值 和 中点
这里最大值 是 m i d − 1 mid - 1 mid−1,也就是 1,最小值 依旧是数组的起点长度,也就是 0,中点 就为 0.5 向下取整,还是 0。
1 4 10 12 17 18 21 25 鉴于 红+蓝=紫,所以这里将 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)。
以上是关于二分算法 原理 及 复杂度 详解的主要内容,如果未能解决你的问题,请参考以下文章