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

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

相关推荐
汀、人工智能5 小时前
[特殊字符] 第21课:最长有效括号
数据结构·算法·数据库架构·图论·bfs·最长有效括号
Boop_wu5 小时前
[Java 算法] 字符串
linux·运维·服务器·数据结构·算法·leetcode
watson_pillow5 小时前
c++ 协程的初步理解
开发语言·c++
故事和你915 小时前
洛谷-算法1-2-排序2
开发语言·数据结构·c++·算法·动态规划·图论
Fcy6486 小时前
算法基础详解(三)前缀和与差分算法
算法·前缀和·差分
kvo7f2JTy6 小时前
基于机器学习算法的web入侵检测系统设计与实现
前端·算法·机器学习
List<String> error_P6 小时前
蓝桥杯最后几天冲刺:暴力大法(一)
算法·职场和发展·蓝桥杯
Tanecious.7 小时前
蓝桥杯备赛:Day6-B-小紫的劣势博弈 (牛客周赛 Round 85)
c++·蓝桥杯
流云鹤7 小时前
Codeforces Round 1090 (Div. 4)
c++·算法
小菜鸡桃蛋狗7 小时前
C++——string(上)
开发语言·c++