c++二分

C++ 二分查找完整教程:零基础看懂、直接套用的万能模板(刷题必备)

二分查找是算法入门最重要、性价比最高的算法。 只需要满足一个条件:数组有序,就能把时间复杂度从 O(n) 优化到 O(logn)。 面试、笔试、LeetCode 刷题必考

今天这篇文章,我不讲废话,只讲:核心思想 + 两套万能模板 + 边界详解 + 常见坑,看完直接刷题。

一、二分查找核心思想

一句话总结:每次排除一半不可能的区间,快速缩小范围

有序数组中,不需要逐个遍历,只需要对比中间元素,就能判断答案在左边还是右边。

  • 中间值 小于 目标:答案一定在右边

  • 中间值 大于 目标:答案一定在左边

  • 中间值 等于 目标:找到答案

二、最稳的二分区间规则(必看)

新手 90% 的 bug 都是区间边界混乱导致的。 本文统一使用最稳妥、最好理解的:闭区间 [left, right]

  • left = 0

  • right = 数组长度 - 1

  • 循环条件:left <= right

三、模板一:基础二分(精准查找)

适用场景:无重复数组,查找某个数是否存在

找到返回下标,找不到返回 -1

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

// 基础二分查找
int binarySearch(vector<int>& nums, int target)
{
    int left = 0;
    int right = nums.size() - 1;

    while (left <= right)
    {
        // 防溢出写法,不写 (left+right)/2
        int 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 main()
{
    vector<int> arr = {1,3,5,7,9,11,13};
    cout << binarySearch(arr,7) << endl;  // 输出 3
    cout << binarySearch(arr,6) << endl;  // 输出 -1
    return 0;
}

重点解释

  • mid = left + (right-left)/2 防止 (left+right) 溢出

  • 为什么 mid±1mid 已经判断过,一定可以排除

  • left <= right 保证区间内所有数都被检查

四、模板二:处理重复数(找左右边界)

真实刷题大部分数组有重复元素。 比如:[1,2,2,2,3],我们经常需要找:

  • 第一个 2(左边界)

  • 最后一个 2(右边界)

1. 寻找左边界(第一个等于 target 的位置)

int findLeftBound(vector<int>& nums, int target)
{
    int left = 0;
    int right = nums.size() - 1;
    int res = -1;

    while (left <= right)
    {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target)
        {
            res = mid;     // 先记录答案
            right = mid - 1;// 继续往左找更靠前的
        }
        else if (nums[mid] < target)
            left = mid + 1;
        else
            right = mid - 1;
    }
    return res;
}

2. 寻找右边界(最后一个等于 target 的位置)

int findRightBound(vector<int>& nums, int target)
{
    int left = 0;
    int right = nums.size() - 1;
    int res = -1;

    while (left <= right)
    {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target)
        {
            res = mid;      // 先记录答案
            left = mid + 1; // 继续往右找更靠后的
        }
        else if (nums[mid] < target)
            left = mid + 1;
        else
            right = mid - 1;
    }
    return res;
}

五、C++ STL 自带二分函数(工作/比赛偷懒神器)

不需要自己手写,直接调用库函数!

#include <algorithm>

// 1. 是否存在
binary_search(nums.begin(),nums.end(),target); 

// 2. 第一个 >= target 的位置(左边界)
lower_bound(nums.begin(),nums.end(),target);

// 3. 第一个 > target 的位置
upper_bound(nums.begin(),nums.end(),target);

六、新手最常见 3 个坑(一次性避坑)

坑1:数组无序也想用二分

二分的前提一定是有序,无序数组二分结果完全随机。

坑2:写死 mid = (left+right)/2

数据量大时会 int 溢出,必须使用mid = left + (right-left)/2

坑3:找到 target 直接停止,无法处理重复数

有重复元素时,找到不能立刻 return,要继续收缩区间找边界

七、博客总结(背诵版)

  • 二分核心:有序、折半、缩区间

  • 基础查找:找到即返回,mid±1 缩区间

  • 边界查找:找到不返回,继续向一侧收缩

  • 永远使用 left+(right-left)/2 防溢出

  • 刷题 90% 的二分题,两套模板足以通杀

posted @ 2026-08-06 13:00  *抽象系数天花板*  阅读(6)  评论(0)    收藏  举报