C++ 中二分查找库函数

函数简介

C++ 标准库中提供了三个和二分查找相关的函数,都定义在 头文件中,非常实用而且高效,下面是它们的功能和使用方法:

✅ 1. binary_search

📌 判断某个元素是否存在于有序数组中

#include

bool found = binary_search(nums.begin(), nums.end(), target);

•	返回值:true 表示找到了 target,否则为 false。
•	时间复杂度:O(log n)

✅ 2. lower_bound

📌 查找第一个 大于等于 target 的元素的位置(返回迭代器)

auto it = lower_bound(nums.begin(), nums.end(), target);
int index = it - nums.begin(); // 获取下标

•	如果 target 存在,返回它的第一个出现位置;
•	如果不存在,返回第一个大于 target 的元素位置;
•	若返回 nums.end(),说明没有比 target 大或等于它的元素。

✅ 3. upper_bound

📌 查找第一个 大于 target 的元素的位置(返回迭代器)

auto it = upper_bound(nums.begin(), nums.end(), target);
int index = it - nums.begin(); // 获取下标

•	如果 target 存在多次,upper_bound 返回的是最后一个的下一个位置;
•	若返回 nums.end(),说明所有元素都 ≤ target。

🔁 三者比较总结:

函数名 返回含义 用法 时间复杂度
binary_search 是否存在 target binary_search(v.begin(), v.end(), x) O(log n)
lower_bound 第一个 ≥ target 的位置 lower_bound(v.begin(), v.end(), x) O(log n)
upper_bound 第一个 > target 的位置 upper_bound(v.begin(), v.end(), x) O(log n)

🧪 举个例子:

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

int main() {
    vector<int> nums = {1, 2, 4, 4, 5, 6};
    int target = 4;

    cout << binary_search(nums.begin(), nums.end(), target) << endl; // 1 (true)
    cout << lower_bound(nums.begin(), nums.end(), target) - nums.begin() << endl; // 2
    cout << upper_bound(nums.begin(), nums.end(), target) - nums.begin() << endl; // 4

    return 0;
}

适用场景

🧩 示例 1:插入一个数使数组仍然有序

vector<int> nums = {1, 3, 5, 7};
int target = 4;

// 插入 target 保持升序
auto it = lower_bound(nums.begin(), nums.end(), target);
nums.insert(it, target);  // 插入到合适位置

// 结果:nums = {1, 3, 4, 5, 7}

🎯 示例 2:查找数组中第一个 ≥ target 的元素

vector<int> nums = {1, 3, 5, 7, 9};
int target = 6;

auto it = lower_bound(nums.begin(), nums.end(), target);

if (it != nums.end()) {
    cout << "第一个 ≥ " << target << " 的元素是 " << *it << endl;
} else {
    cout << "所有元素都小于 " << target << endl;
}

🎯 示例 3:查找数组中第一个 > target 的元素

vector<int> nums = {1, 3, 5, 7, 9};
int target = 5;

auto it = upper_bound(nums.begin(), nums.end(), target);

if (it != nums.end()) {
    cout << "第一个 > " << target << " 的元素是 " << *it << endl;
}

🔁 示例 4:查找元素出现的次数(重复元素)

vector<int> nums = {1, 3, 3, 3, 5, 7};
int target = 3;

// 出现次数 = upper_bound - lower_bound
int count = upper_bound(nums.begin(), nums.end(), target)
          - lower_bound(nums.begin(), nums.end(), target);

cout << "数字 " << target << " 出现了 " << count << " 次" << endl;

🎯 示例 5:查找离 target 最近的数

vector<int> nums = {1, 3, 6, 8, 10};
int target = 5;

auto it = lower_bound(nums.begin(), nums.end(), target);
int closest;

if (it == nums.begin()) {
    closest = *it;
} else if (it == nums.end()) {
    closest = *(--it);
} else {
    int a = *it;
    int b = *(--it);
    closest = (abs(a - target) < abs(b - target)) ? a : b;
}

cout << "离 " << target << " 最近的数是 " << closest << endl;

例题

https://leetcode.cn/problems/maximum-count-of-positive-integer-and-negative-integer/
给你一个按 非递减顺序 排列的数组 nums ,返回正整数数目和负整数数目中的最大值。

换句话讲,如果 nums 中正整数的数目是 pos ,而负整数的数目是 neg ,返回 pos 和 neg二者中的最大值。
注意:0 既不是正整数也不是负整数。

示例 1:

输入:nums = [-2,-1,-1,1,2,3]
输出:3
解释:共有 3 个正整数和 3 个负整数。计数得到的最大值是 3 。
示例 2:

输入:nums = [-3,-2,-1,0,0,1,2]
输出:3
解释:共有 2 个正整数和 3 个负整数。计数得到的最大值是 3 。
示例 3:

输入:nums = [5,20,66,1314]
输出:4
解释:共有 4 个正整数和 0 个负整数。计数得到的最大值是 4 。

提示:

1 <= nums.length <= 2000
-2000 <= nums[i] <= 2000
nums 按 非递减顺序 排列。

进阶:你可以设计并实现时间复杂度为 O(log(n)) 的算法解决此问题吗?

#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    int maximumCount(vector<int>& nums) {
        // 统计负数:最后一个 <0 的位置 +1
        int neg = upper_bound(nums.begin(), nums.end(), -1) - nums.begin();
        
        // 统计正数:end - 第一个 >0 的位置
        int pos = nums.end() - lower_bound(nums.begin(), nums.end(), 1);
        
        return max(neg, pos);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值