[数组] - LeetCode 704. 二分查找

LeetCode 704. 二分查找

本题的核心在于统一搜索区间的定义 ------始终将区间视为闭区间 [left, right],并确保循环条件与区间更新逻辑严格匹配。

java 复制代码
class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1; // 闭区间 [left, right]
        while (left <= right) {              // 区间非空时继续
            int mid = (left + right) >> 1;
            if (target < nums[mid]) {
                right = mid - 1;             // 更新右边界(排除 mid)
            } else if (nums[mid] < target) {
                left = mid + 1;              // 更新左边界(排除 mid)
            } else {
                return mid;                  // 命中目标
            }
        }
        return -1;                           // 未找到
    }
}

进阶思考:二分查找的边界陷阱与两种区间定义

1. 为什么推荐闭区间 [left, right]

闭区间定义具有以下优势:

  • 语义直观left <= right 直接对应"区间非空"的数学定义
  • 边界处理自然right = mid - 1left = mid + 1 的更新逻辑与区间定义完全一致
  • 避免死循环 :不会出现 left == right 时无法退出的情况

2. 开区间 (left, right) 的写法对比

若采用左闭右开区间 [left, right),需要调整:

java 复制代码
int left = 0, right = nums.length; // 注意 right 初始值
while (left < right) {             // 区间非空条件变为 <
    int mid = left + (right - left) / 2;
    if (target < nums[mid]) {
        right = mid;               // 关键区别:保持右开
    } else if (nums[mid] < target) {
        left = mid + 1;
    } else {
        return mid;
    }
}

3. 高频错误场景

错误1:边界溢出
java 复制代码
// 错误写法(当 left + right 可能溢出时)
int mid = (left + right) / 2;
// 正确写法
int mid = left + (right - left) / 2;
错误2:区间更新逻辑矛盾
java 复制代码
// 错误:区间定义为 [left, right] 但更新为 right = mid
if (target < nums[mid]) {
    right = mid; // 此时 mid 仍在区间内,可能导致死循环
}

4. 模板扩展:寻找左右边界

寻找左边界(第一个 ≥ target 的位置)
java 复制代码
int leftBound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (target <= nums[mid]) {
            right = mid - 1; // 保留 mid 作为候选
        } else {
            left = mid + 1;
        }
    }
    return left; // 需检查 left 是否越界
}
寻找右边界(最后一个 ≤ target 的位置)
java 复制代码
int rightBound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (target < nums[mid]) {
            right = mid - 1;
        } else {
            left = mid + 1; // 保留 mid 作为候选
        }
    }
    return right; // 需检查 right 是否越界
}
相关推荐
李老师讲编程3 分钟前
C++信息学奥赛练习题-杨辉三角
数据结构·c++·算法·青少年编程·信息学奥赛
冠希陈、4 分钟前
PHP 判断是否是移动端,更新鸿蒙系统
android·开发语言·php
zxsz_com_cn13 分钟前
设备预测性维护算法核心功能有哪些?六大模块拆解智能运维的“技术骨架”
运维·算法
期末考复习中,蓝桥杯都没时间学了15 分钟前
力扣刷题13
数据结构·算法·leetcode
HDO清风25 分钟前
CASIA-HWDB2.x 数据集DGRL文件解析(python)
开发语言·人工智能·pytorch·python·目标检测·计算机视觉·restful
2201_7569890925 分钟前
C++中的事件驱动编程
开发语言·c++·算法
会飞的战斗鸡31 分钟前
JS中的链表(含leetcode例题)
javascript·leetcode·链表
多米Domi01136 分钟前
0x3f 第48天 面向实习的八股背诵第五天 + 堆一题 背了JUC的题,java.util.Concurrency
开发语言·数据结构·python·算法·leetcode·面试
2301_8223776537 分钟前
模板元编程调试方法
开发语言·c++·算法
csbysj202040 分钟前
Python 循环嵌套
开发语言