二分查找(1)

一.题目

704. 二分查找 - 力扣(LeetCode)

二.思路

提到二分查找 ,很多人第一反应就是"数组必须有序"。其实,这种说法并不准确。二分查找真正的前提是数组具有二分性 。那么,什么是二分性呢?

简单来说,如果你能在数组中找到一个点,将数组划分为三个部分:左区域该点右区域 ,并且能够根据某种规则确定目标位于哪一侧,那么这个数组就具备了二分性 。之所以我们常说"有序才能二分",是因为有序性 是最常见、最简单的规律------它满足左区域 < 中点 < 右区域 ,从而可以轻松判断目标在左边还是右边。可以说,有序只是二分性的一种特例,因为它足够简单,所以流传最广。

三.代码演示

cpp 复制代码
class Solution {
public:
    int search(vector<int>& nums, int target) 
    {
        int left = 0;
        int right = nums.size()-1;
        while(left <= right)
        {
            //left+(right - left)/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;
    }
};

四.代码讲解

第一步:问题理解与前提

  • 本题给定一个升序排列 的整数数组 nums 和一个目标值 target,要求返回 target 在数组中的索引,如果不存在则返回 -1。

  • 由于数组有序,具备二分性 ,我们可以利用二分查找算法高效求解。


第二步:初始化左右指针

  • 定义左指针 left = 0,指向数组第一个元素。

  • 定义右指针 right = nums.size() - 1,指向数组最后一个元素。

  • 这两个指针用于维护当前搜索的区间,初始为整个数组。


第三步:循环查找

  • 使用 while 循环,条件为 left <= right
    为什么是 <= 而不是 <

    因为当 left == right 时,区间内还有一个元素需要检查,如果此时退出循环就会漏掉该元素。使用 <= 可以确保区间内所有元素都被覆盖。


第四步:计算中间位置(防溢出)

  • 中间位置 mid = left + (right - left) / 2
    为什么不直接用 (left + right) / 2

    leftright 都很大时,left + right 可能超过 int 范围导致溢出。使用 left + (right - left)/2 可以避免此问题,是安全的写法。


第五步:比较中间值与目标

  • 如果 nums[mid] == target,说明找到目标,直接返回 mid

  • 如果 nums[mid] < target,说明目标在右半区间 ,因为数组有序,所有比 mid 小的元素都在左边,而目标更大,所以更新 left = mid + 1,舍弃左半部分。

  • 如果 nums[mid] > target,说明目标在左半区间 ,更新 right = mid - 1,舍弃右半部分。


第六步:循环结束

  • 如果循环结束仍未返回,说明 target 不在数组中,返回 -1

重点总结

  • 二分查找的核心:每次将搜索区间缩小一半,时间复杂度 O(log n)。

  • 循环条件 :必须用 left <= right,确保最后一个元素被检查。

  • 中间值计算 :使用 left + (right - left)/2 避免溢出。

  • 指针更新 :根据比较结果,将 leftright 移动到 mid 的相邻位置,因为 mid 已经检查过,无需再包含。

这个基础二分查找是所有变体(如寻找左右边界、旋转数组等)的基石,理解每一步的逻辑至关重要

相关推荐
北域码匠23 分钟前
高通滤波算法深度解析(High-Pass Filter)
stm32·算法·c#·数字信号处理·嵌入式开发·滤波算法·高通滤波
指掀涛澜天下惊1 小时前
强化学习进阶篇八 策略梯度算法
深度学习·学习·算法·强化学习
乌萨奇也要立志学C++1 小时前
【洛谷】kmp算法
开发语言·算法
禹凕1 小时前
Dijkstra算法详解与应用
python·算法
千谦阙听2 小时前
C++类和对象(中):默认成员函数、构造与析构、拷贝构造、运算符重载
开发语言·c++·学习
YaraMemo2 小时前
元启发式算法框架
人工智能·算法·5g·信息与通信·启发式算法·信号处理
weixin_307779132 小时前
一维无粘 Burgers 方程的激波形成问题:MacCormack 格式求解
c++·算法·matlab
HugoStudio_SWAN3 小时前
洛谷 B4500 / B4449 / B3843 凯撒密码、密码强度与密码合规——加密与安全的三道门
c++·学习·程序人生·算法·安全
雾里看山3 小时前
源码目录、构建目录与 out-of-source build
c++·软件构建·cmake
枫叶林FYL4 小时前
【群体智能集群控制工程实践】第3章 一致性协同算法
算法