查找方式有哪些,效率如何
不同的数据结构有不同的查找效率。
1.底层数据结构是以数组实现的,那么其查找数组下标效率为O(1),查找特定值得效率为O(n)
2.底层数据结构是以链表实现的,那么其查找迭代器(类似于数组查询下标)效率为O(n),查找特定值得效率为O(n)
3.底层数据结构是以哈希表实现的,那么其查找迭代器和特定值效率均为O(1)
当然,以上查找效率只是针对于简单的数据结构而言,优化过的数据结构暂且不谈。
二分查找的目的就是在数组查询存储的特定目标值(target)能够提升其查询效率。
二分查找的时间复杂度为:O(logn) 空间复杂度为:O(1)
二分查找的前提条件
当然对于无序的数组,想要提高查询target的效率是无法做到的。
二分查找需要满足的前提条件是:数组有序排列(升序或者降序)(严格递增或递增均可),升序和降序情况类似。一下均已升序情况讨论
二分查找的形式以及代码实现
三种实现形式:
1.简单查询target值,target位置不唯一。就是说查询一个有序数组中是否存在target值,可能数组中存在多个target。(C++标准库中已经实现 binary_search())
2.查询第一个target值出现的位置,即左边界。就是查询有序数组中第一个出现的target的索引。(C++标准库中的实现 lower_bound())
3.查询最后一个target值出现的位置,即右边界。就是查询有序数组中最后一个target出现的索引。(C++标准库中的实现 upper_bound())
int binary_search ( vector< int > & nums, int target) {
int left = 0 , right = nums. size ( ) - 1 ;
while ( left <= right) {
int middle = left + ( ( right - left) >> 1 ) ;
if ( nums[ middle] == target) return left;
else if ( nums[ middle] < target) left = middle + 1 ;
else if ( nums[ middle] > target) right = middle - 1 ;
}
return - 1 ;
}
int searchLeftRange ( vector< int > & nums, int target) {
int left = 0 , right = nums. size ( ) ;
while ( left < right) {
auto middle = left + ( ( right - left) >> 1 ) ;
if ( nums[ middle] >= target) right = middle;
else left = middle + 1 ;
}
if ( left == nums. size ( ) ) return - 1 ;
return nums[ left] == target ? left : - 1 ;
}
int searchRightRange ( vector< int > & nums, int target) {
left = 0 , right = nums. size ( ) ;
while ( left < right) {
auto middle = left + ( ( right - left) >> 1 ) ;
if ( nums[ middle] <= target) left = middle + 1 ;
else right = middle;
}
if ( left == 0 ) return - 1 ;
return nums[ left - 1 ] == target ? ( left - 1 ) : - 1 ;
}
后记
值得注意的点:搜索区间的选取(左闭右开,左闭右闭)、更新时右边值是否能取到(right = middle - 1 or right = middle)、区间能不存在target时最后的判断条件。
二分查找是一个高频的算法技巧,在算法实现中常常用来优化算法的查找速度,尤其对于数据规模较大的情况下效果尤为明显。