活动地址:CSDN21天学习挑战赛
算法入门系列-二分查找
一、二分查找(binary search)的概念
-
折半查找又叫做二分查找, 是一种效率较高的查找算法,但是前提条件是要求线性表是有序的
-
折半查找的基本思路是首先确定表的中间位置,将关键字与该值进行比较
-
- 如果该值等于关键字则返回该值的索引
- 如果该值小于关键字则在中间位置的左边继续二分查找
- 如果该值大于关键字则在中间位置的右边继续二分查找
-
还有另外一种思路就是递归,因为如果中间值不等于key值,程序就要一直进行二分查找直至找到
二、算法分析
-
数据结构:数组
-
输入:arr = 1,11,22,33,44,55,66,77,88,99 key = 77
-
算法实现:
总体思路大致如下(假设数组是单调不减的):
- 如果该值等于关键字则返回该值的索引
- 如果该值小于关键字则在中间位置的左边继续二分查找
- 如果该值大于关键字则在中间位置的右边继续二分查找
具体实现过程:
- 首先判断数组是否为空
- 建立循环:以查找区间不为空为循环条件(low<high)
- if分支结构进行判断:
-
- 相等时返回逻辑位置
- key小于arr[mid]时将搜索区间缩小为数组前半段
- key大于arr[mid]时将搜索区间缩小为数组后半段
- 循环执行直到找到
-
输出:8
-
算法的时间复杂度:O(log2n)
-
算法的空间复杂度:O(1)
三、算法实现(java)
private static int binarySearch(int[] arr, int key) {
if (arr == null) {
return -1;
}
int low = 0,high = arr.length - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == key) {
return mid+1;//返回逻辑位置
} else if (key < arr[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
递归实现:
public static int binarySearch2(int[] arr,int low,int high, int key){
if (arr == null) {
return -1;
}
int mid = low+(high-low)/2;
if (key==arr[mid]){
return mid+1;// 返回逻辑位置
} else if (key < arr[mid]) {
high = mid-1;
return binarySearch2(arr,low,high,key);
} else if (key > arr[mid]) {
low = mid+1;
return binarySearch2(arr,low,high,key);
}
else {
return -1;
}
}
C++实现:
#include <iostream>
#include <vector>
using namespace std;
vector<int>::iterator binarySearch(vector<int> &,int);
int main()
{
vector<int> v{11,22,33,44,55,66,77,88,99};
auto iterator = binarySearch(v,77);
cout<<*(iterator)<<endl;
}
vector<int>::iterator binarySearch(vector<int> &v,int search)
{
if(v.begin()==v.end())
{
return;
}
else
{
auto begin = v.begin();
auto end = v.end();
auto mid = v.begin()+(v.end()-v.begin())/2;
while(begin<end)
{
if(*mid<search)
{
begin = mid+1;
}
else if(*mid>search)
{
end = mid-1;
}
else
{
return mid;
}
}
}
}
四、进阶
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
本题与上面不同之处在于存在目标值不存在于数组中的情况,因此需要考虑这种情况。
C实现
int searchInsert(int* nums, int numsSize, int target){
int low=0,high=0;
while(low<=high)
{
int mid = low + (high-low)/2;
if(nums[mid] > target)
{
high = mid -1;
}
else if(nums[mid] < target)
{
low = mid + 1;
}
else
return mid;
}
return low;//数组中不存在目标值的情况
}
作者:LeetCode
链接:https://leetcode.cn/leetbook/read/array-and-string/cxqdh/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
五、总结
- 虽然二分查找的效率高,但要求查找表是按关键字有序的
- 二分查找需确定查找区间,因此要求查找表的存储结构具有随机存取特性,所以只适用于顺序表,不适合于链式存储结构,需要注意的是,不能说二分查找不能用于链式存储结构,只是说采用顺序表时二分查找算法设计更方便,效率更高
刚开始写博客,文章中难免会有纰漏,如有不足,欢迎各位批评指点。