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

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

相关推荐
旖-旎2 分钟前
《LeetCode 417 太平洋大西洋水流问题 FloodFill DFS 解法》
c++·算法·深度优先·力扣·floodfill
凌波粒5 分钟前
LeetCode--46.全排列(回溯算法)
数据结构·算法·leetcode
鱼子星_10 分钟前
C++从零开始系列篇(二):C++入门——函数重载,引用,inline与nullptr
开发语言·c++·笔记
2zcode19 分钟前
项目文档:基于MATLAB语音信号变声算法设计与实现
算法·matlab·语音识别
指令集梦境24 分钟前
图解:单调栈算法模板(Java语言)
java·开发语言·算法
小灰灰搞电子33 分钟前
C++ boost::circular_buffer 详解:原理、用法与实战
开发语言·c++·boost
生成论实验室1 小时前
自动驾驶:一个自主运动的系统
人工智能·算法·机器学习·语言模型·机器人·自动驾驶·安全架构
sheeta19981 小时前
LeetCode 每日一题笔记 日期:2026.06.16 题目:3612. 字符串特殊符号处理
笔记·算法·leetcode
青山木1 小时前
Hot 100 --- 矩阵置零
线性代数·算法·leetcode·矩阵·哈希算法
Jasmine_llq1 小时前
《B4264 [GESP202503 四级] 二阶矩阵》
线性代数·算法·矩阵·二维矩阵遍历枚举所有2×2矩阵·交叉乘积等式条件判断·输入输出快读加速·长整型防溢出计数统计