二分查找(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 已经检查过,无需再包含。

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

相关推荐
GreenTea8 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
码匠许师傅8 小时前
【C++ 面试真题】聊聊 C++ 的移动语义与右值引用
java·c++·面试
fqq39 小时前
力扣刷题前置Java语法
算法·leetcode·职场和发展
小小龙学IT10 小时前
DuckDB 深度实战:用 C++ 在进程内跑一个「分析型数据库」
数据库·c++
知无不研11 小时前
lambda表达式的使用(3)
开发语言·c++·lambda
2501_9065651211 小时前
数学之美探究
算法
oier_Asad.Chen11 小时前
【洛谷题解/AcWing题解/OI学习笔记】洛谷P2868【USACO07DEC】Sightseeing Cows G(01分数规划求最大比率)
算法·图论·spfa·二分·负环
C++ 老炮儿的技术栈13 小时前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
leisoo809713 小时前
财报数据怎么排雷本地化Python构建财务异常预警系统
人工智能·python·算法
qz_Serene15 小时前
C++:类和对象(上)
开发语言·c++