二分查找算法

c++表中库函数

std::lower_bound(x) //返回第一个>=x的元素迭代器
std::upper_bound(x) //返回第一个>x的元素的迭代器

注意:查找的返回值为迭代器,查找失败返回末尾元素的后一个位置
ex:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
	vector<int> a = {1,2,3,4,5,6,7,8,9,10}; 
	if(lower_bound(a.begin(),a.end(),0)!=a.end()){
		cout << "yes" <<endl;
	}
	return 0;
 }

二分查找算法的实现

B站一篇非常棒的讲解,视频链接:二分查找为什么总是写错?
代码模板:

//搜索区间为[0,N - 1]
int l = -1, r = N;
while(l + 1 != r) {
	int mid = l + r >> 1; //(l + r) / 2 向下取整
	if(check(mid)) l = mid;
	else r = mid;
}
return l or r; //根据需要选择返回的值

简单理解,最开始左指针指向索引为-1(第一个元素的前一个位置),右指针指向最后一个元素的后一个位置,算法执行完后左指针和右指针紧挨着,将数组分成两部分,l指向左边部分的最后一个元素,r指向右边部分的第一个元素,通过设定check条件和返回左指针or右指针,得到你想要的结果。具体看下图。
视频中问题的答案
以找到第一个>=5的元素为例

//搜索区间为[0,N - 1]
int l = -1, r = N;
while(l + 1 != r) {
	int mid = l + r >> 1; //(l + r) / 2 向下取整
	if(nums[mid] < 5) l = mid;
	else r = mid;
}
return r;

练习题

Leetcode 278. 第一个错误的版本
Leetcode 34. 在排序数组中查找元素的第一个和最后一个位置
Leetcode 35. 搜索插入位置

代码
Leetcode 278. 第一个错误的版本

class Solution {
public:
    int firstBadVersion(int n) {
        long long l = -1, r = 1ll + n;
        while(r - l > 1) {
            long long mid = r + l >> 1;
            if(isBadVersion(mid)) r = mid;
            else l = mid;
        }
        return r;
    }
};

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

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int> ans;
        bool t = false;
        long long l = -1, r = nums.size();
        while (r - l > 1) {
            long long mid = l + r >> 1;
            if(nums[mid] == target) t = true;
            if (nums[mid] >= target) r = mid;
            else l = mid;
        }
        if(!t) return {-1,-1};
        ans.push_back(r);
        l = - 1, r = nums.size();
        while(r - l > 1) {
            long long mid = l + r >> 1;
            if(nums[mid] <= target) l = mid;
            else r = mid;
        }
        ans.push_back(l);
        return ans;
    }
};
//Leetcode34 官方题解 时间100%代码
class Solution 
{ 
public:
    int binarySearch(vector<int>& nums, int target, bool lower) 
    {
        int left = 0, 
        right = (int)nums.size() - 1, 
        ans = (int)nums.size();
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] > target || (lower && nums[mid] >= target)) {
                right = mid - 1;
                ans = mid;
            } 
            else 
            {
                left = mid + 1;
            }
        }
        return ans;
    }

    vector<int> searchRange(vector<int>& nums, int target) 
    {
        int leftIdx = binarySearch(nums, target, true);
        int rightIdx = binarySearch(nums, target, false) - 1;
        if (leftIdx <= rightIdx && rightIdx < nums.size() && nums[leftIdx] == target && nums[rightIdx] == target) 
        {
            return vector<int>{leftIdx, rightIdx};
        } 
        return vector<int>{-1, -1};
    }
};
  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值