二分查找,二分搜索

二分查找

二分查找就是比较高效的的查找算法。


一、二分查找

#include<iostream>
#include<vector>
using namespace std;
//缺点:遇到重复数字时,只能查找中间的目标数字
int search(vector<int>& nums, int target) {
        int left=0,right=nums.size()-1,mid=0;
        while(left<=right){   //=是为了防止漏掉left==right的情况
            mid=left+(right-left)/2;   //防止溢出
            if(nums[mid]==target)
                return mid;
            //刚才的搜索区间是左闭右闭的
            else if(nums[mid]<target)
                left=mid+1;
            else
                right=mid-1;
        }
        return -1;
}

二、寻找左侧边界的二分搜索

    int search(vector<int>& nums, int target) {
       int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else if (nums[mid] == target) {
                // 别返回,锁定左侧边界
                right = mid - 1;
            }
        }
        // 判断 target 是否存在于 nums 中
        // 此时 target 比所有数都大,返回 -1
        if (left == nums.length) return -1;
        // 判断一下 nums[left] 是不是 target
        return nums[left] == target ? left : -1;
    }

三 、右侧边界的二分搜索

     int search(vector<int>& nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            } else if (nums[mid] == target) {
                // 别返回,锁定右侧边界
                left = mid + 1;
            }
        }
        // 此时 left - 1 索引越界
        if (left - 1 < 0) return -1;
        // 判断一下 nums[left] 是不是 target
        return nums[left - 1] == target ? (left - 1) : -1;
    }

高级函数

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    // 1.基础用法
    vector<int> increasing = {1,2,3,4,5};

    int pos = upper_bound(increasing.begin(), increasing.end(), 3) - increasing.begin();
    cout << increasing[pos] << endl;   // 4(第一个大于3的数)

    pos = lower_bound(increasing.begin(), increasing.end(), 3) - increasing.begin();
    cout << increasing[pos] << endl;   // 3(第一个大于等于3的数)

    bool res = upper_bound(increasing.begin(), increasing.end(), 5) == increasing.end();
    cout << res << endl;               // 1 (true,即:第一个大于5的数不存在)

    // 2.greater重载
    vector<int> decreasing = {5,4,3,2,1};

    pos = upper_bound(decreasing.begin(), decreasing.end(), 3, greater<int>()) - decreasing.begin();
    cout << decreasing[pos] << endl;   // 2(第一个小于3的数)

    pos = lower_bound(decreasing.begin(), decreasing.end(), 3, greater<int>()) - decreasing.begin();
    cout << decreasing[pos] << endl;   // 3(第一个小于等于3的数)

    res = lower_bound(decreasing.begin(), decreasing.end(), 0, greater<int>()) == decreasing.end();
    cout << res << endl;               // 1 (true,即:第一个小于等于0的数不存在)

    // 3.进阶用法
    pos = upper_bound(increasing.begin(), increasing.end(), 3, [](int value, int element) -> bool {
        return value < element;
    }) - increasing.begin();           // 等价于基础用法中的第1句
    cout << increasing[pos] << endl;   // 4(value是3,第一个大于value的数)

    pos = upper_bound(increasing.begin(), increasing.end(), 3, [](int value, int element) -> bool {
        return value <= element;
    }) - increasing.begin();           // 等价于基础用法中的第2句
    cout << increasing[pos] << endl;   // 3(value是3,第一个大于等于value的数)

    pos = lower_bound(increasing.begin(), increasing.end(), 3, [](int element, int value) -> bool {
        return element < value;
    }) - increasing.begin();           // 等价于基础用法中的第2句
    cout << increasing[pos] << endl;   // 3(value是3,第一个大于等于value的数)

    pos = lower_bound(increasing.begin(), increasing.end(), 3, [](int element, int value) -> bool {
        return element <= value;
    }) - increasing.begin();           // 等价于基础用法中的第1句
    cout << increasing[pos] << endl;   // 4(value是3,第一个大于value的数)
    
    return 0;
}

作者:htcomeon
链接:https://leetcode.cn/circle/article/QKJ2g2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

总结

就这了,代码自己好好看看

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

代码有点萌

谢谢

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

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

打赏作者

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

抵扣说明:

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

余额充值