二分查找:迭代与递归实现全解析

一、二分查找的核心原理

二分查找仅适用于有序的数组 / 容器,核心逻辑是:

  1. 定义查找区间 [left, right](闭区间);
  2. 计算区间中点 mid = left + (right - left) / 2(避免 (left+right)/2 导致的整数溢出);
  3. 对比 nums[mid] 与目标值 target,缩小区间:
    • nums[mid] == target:找到目标,返回索引;
    • nums[mid] < target:目标在右半区间,更新 left = mid + 1
    • nums[mid] > target:目标在左半区间,更新 right = mid - 1
  4. left > right 时,区间无效,说明无目标值,返回 -1

二、迭代版实现(基础版)

cpp 复制代码
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1; // 闭区间右边界
        
        while (left <= right) { // 区间有效时循环
            int mid = left + (right - left) / 2; // 安全计算mid
            if (nums[mid] == target) {
                return mid; // 找到目标,直接返回
            } else if (nums[mid] < target) {
                left = mid + 1; // 右半区间,排除mid
            } else {
                right = mid - 1; // 左半区间,排除mid
            }
        }
        return -1; // 未找到目标
    }
};

迭代版关键注意点

  1. 区间边界 :采用闭区间 [left, right],因此循环条件是 left <= right(当 left == right 时,区间仍有一个元素需要检查);
  2. mid 计算left + (right - left) / 2 等价于 (left + right) / 2,但避免了 left + right 超出 int 范围的溢出问题;
  3. 边界更新 :必须用 mid + 1/mid - 1,而非 left + 1/right - 1,否则会退化为顺序查找,失去二分优势。

三、递归版实现(进阶版)

递归版将循环逻辑替换为函数自身调用,核心是 "终止条件 + 缩小区间递归"。

cpp 复制代码
class Solution {
public:
    // 对外接口:保持简洁,初始化递归区间
    int search(vector<int>& nums, int target) {
        return binarySearch(nums, target, 0, nums.size() - 1);
    }

private:
    // 递归辅助函数:承载核心逻辑,传递区间参数
    int binarySearch(vector<int>& nums, int target, int left, int right) {
        // 递归终止条件:区间无效,返回-1
        if (left > right) {
            return -1;
        }
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            // 递归查找右半区间
            return binarySearch(nums, target, mid + 1, right);
        } else {
            // 递归查找左半区间
            return binarySearch(nums, target, left, mid - 1);
        }
    }
};

递归版核心坑点(新手必看)

  1. 终止条件优先 :必须先判断 left > right,否则会无限递归导致栈溢出;
  2. 返回值传递
    • 主函数需 return 递归调用的结果,否则违反函数返回值声明;
    • 递归分支需 return 子递归的结果,否则递归结果无法层层回传(最易踩坑);
  3. 辅助函数设计 :对外接口保持和迭代版一致,通过辅助函数传递 left/right,兼顾易用性与递归逻辑。

四、常见错误总结

  1. 语法错误:nums.size 忘记加括号(size() 是 vector 成员函数);
  2. 逻辑错误:边界更新用 left + 1 替代 mid + 1
  3. 递归错误:缺失 return 传递递归结果;
  4. 溢出错误:直接用 (left + right) / 2 计算 mid。

五、总结

  1. 二分查找的核心是闭区间 + 中点对比 + 区间收缩,迭代与递归的核心逻辑完全一致;
  2. 迭代版注重效率,是工程实践的首选;递归版注重逻辑直观,适合理解算法本质;
  3. 无论哪种实现,mid 计算、边界更新、终止条件是三大核心,也是新手最易出错的点。
相关推荐
做怪小疯子2 小时前
Leetcode刷题——深度优先搜索(DFS)
算法·leetcode·深度优先
大数据AI人工智能培训专家培训讲师叶梓2 小时前
120B 数学语料 + GRPO 算法,DeepSeekMath 刷新开源大模型推理天花板
人工智能·算法·大模型·推理·deepseek·openclaw·openclaw 讲师
IMPYLH2 小时前
Linux 的 comm 命令
linux·运维·算法
薛定谔的悦2 小时前
嵌入式设备OTA升级实战:从MQTT命令到自动重启的全流程解析
linux·算法·ota·ems
杰克尼2 小时前
知识点总结--01
数据结构·算法
cici158742 小时前
图像匹配算法:灰度相关法、相位相关法与金字塔+相位相关法
算法
佚名ano2 小时前
支持向量机SVM的简单推导过程
算法·机器学习·支持向量机
云泽8082 小时前
蓝桥杯算法精讲:倍增思想与离散化深度剖析
算法·职场和发展·蓝桥杯
m0_569881472 小时前
基于C++的数据库连接池
开发语言·c++·算法