必学算法——二分查找

前言

二分查找是是必学算法之一,蓝桥杯、acm等竞赛都大概率会出现,面试的时候也需要用到,所以我们要熟练掌握,下面让我们来深入了解二分查找的应用场景。
燃起来了

零、二分查找的概念

二分查找,也称为折半查找(Binary Search),是一种在 有序数组 中查找特定元素的搜索算法。 它的基本思想是将目标值与数组中间的元素进行比较,如果目标值小于中间元素,则在数组的左半部分继续查找,否则在右半部分查找,不断缩小搜索范围,直到找到目标值或确定目标值不存在为止。 二分查找的时间复杂度为 O (logn) ,即查找效率较高。

一、动态图解

在这里插入图片描述

二、经典例题

1、收索插入位置

(帅哥们这个蓝色字体可以点进去看原题)

1.1、解题思路

定义两个游标代表左区间(l)和右区间r的端点,然后找中间(mid)端点,如果该位置的值大于(a[mid]>=value)等于我们要找的值,那么将右端点压缩一半区间,将r=mid。反之,将r=mid。重复进行此次循环,循环条件为l<r,循环结束后只剩下l与r两个端点,因为a[r]>=value,所以只需要判断a[r]是否等于value即可,如果等于说明找到了,反之,没找到。

1.2、代码题解

class Solution {
    bool isGreen(vector<int>&nums,int m,int t){
        return nums[m]>=t;//判断nums[mid]的值是否大于等于要找的值
    }
    int bSearch(vector<int>& nums,int t){
        int l=-1;
        int r=nums.size();
        while(l+1<r){
            int mid=(l+r)/2;
            if(isGreen(nums,mid,t)){
                r=mid;
            }
            else l=mid;
        }
        return r;
    }
public:
    int searchInsert(vector<int>& nums, int target) {
        return bSearch(nums,target);
    }
};

2、二分查找

2.1、解题思路

这题和第一题一样就是用红绿灯标记法进行二分查找,相信前面的题目理解了,这题你也能胸有成竹的写出来。

2.2、代码题解

class Solution {
    bool isGreen(vector<int>& nums,int m,int t){
        return nums[m]>=t;
    }

    int bSearch(vector<int>& nums,int t){
        int l=-1,r=nums.size();
        while(l+1<r){
            int mid=(l+r)/2;
            if(isGreen(nums,mid,t))r=mid;
            else l=mid;
        }
        return r;
    }
public:
    int search(vector<int>& nums, int target) {
        int ret=bSearch(nums,target);
        if(ret==nums.size())return -1;//r等于数组最右端说明所有值都比target小就找不到
        if(nums[ret]!=target)return -1;//找到了大于等于target的值,但是不等于说明只有nums[ret]>target这种情况
        return ret;
    }
};

2、在排序数组中查找元素的第一个和最后一个位置

2.1、解题思路

这一题稍微有点难度,但是也不多,其实总体思路和前面两题都一样,就是多了一个条件,我们要找结束位置, 这个结束位置也就是找出大于等于目标值加一(target+1<=a[i])的最小下标r,然后r-1就是目标值的结束位置,这个要好好理解,我相信你能想出来。

2.2、代码题解

class Solution {
    bool isGreen(vector<int>& nums, int m,int t){
        return nums[m]>=t;
    }
    int bSearch(vector<int>& nums, int t){
        int l=-1,r=nums.size();
        while(l+1<r){
            int mid=(l+r)/2;
            if(isGreen(nums,mid,t))r=mid;
            else l=mid;
        }
        return r;
    }
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int>ans;
        int idx1=bSearch(nums,target);
        int idx2=bSearch(nums,target+1);
        if(idx1==nums.size())return {-1,-1};
        if(nums[idx1]!=target)return {-1,-1};
        ans.push_back(idx1);
        ans.push_back(idx2-1);
        return ans;
    }
};

都看到这里了,希望帅哥你能点赞关注多多支持一下,非常感谢。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值