【算法入门系列】二分查找


活动地址:CSDN21天学习挑战赛

算法入门系列-二分查找

一、二分查找(binary search)的概念

  • 折半查找又叫做二分查找, 是一种效率较高的查找算法,但是前提条件是要求线性表是有序的

  • 折半查找的基本思路是首先确定表的中间位置,将关键字与该值进行比较

    • 如果该值等于关键字则返回该值的索引
    • 如果该值小于关键字则在中间位置的左边继续二分查找
    • 如果该值大于关键字则在中间位置的右边继续二分查找
  • 还有另外一种思路就是递归,因为如果中间值不等于key值,程序就要一直进行二分查找直至找到

二、算法分析

  1. 数据结构:数组

  2. 输入:arr = 1,11,22,33,44,55,66,77,88,99 key = 77

  3. 算法实现:

总体思路大致如下(假设数组是单调不减的):

  • 如果该值等于关键字则返回该值的索引
  • 如果该值小于关键字则在中间位置的左边继续二分查找
  • 如果该值大于关键字则在中间位置的右边继续二分查找

具体实现过程:

  • 首先判断数组是否为空
  • 建立循环:以查找区间不为空为循环条件(low<high)
  • if分支结构进行判断:
    • 相等时返回逻辑位置
    • key小于arr[mid]时将搜索区间缩小为数组前半段
    • key大于arr[mid]时将搜索区间缩小为数组后半段
    • 循环执行直到找到
  1. 输出:8

  2. 算法的时间复杂度:O(log2n)

  3. 算法的空间复杂度: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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

五、总结

  1. 虽然二分查找的效率高,但要求查找表是按关键字有序的
  2. 二分查找需确定查找区间,因此要求查找表的存储结构具有随机存取特性,所以只适用于顺序表,不适合于链式存储结构,需要注意的是,不能说二分查找不能用于链式存储结构,只是说采用顺序表时二分查找算法设计更方便,效率更高

刚开始写博客,文章中难免会有纰漏,如有不足,欢迎各位批评指点。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指针到处飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值