LeetCode 704.「二分查找」的 2 种解法(JS 代码实现)

224 阅读3分钟

二分查找(Binary Search)是算法面试和刷题中最常见、最基础的算法之一。它的核心思想是“分而治之”,每次都把查找范围缩小一半,大大提高了查找效率。本文将用最通俗的语言,带你分析二分查找的两种常见写法


一、二分查找适用场景

二分查找适用于有序且无重复元素的数组。比如:[1, 3, 5, 7, 9] 这样的数组。


二、两种区间写法

二分查找的核心是“区间”,常见有两种写法:

  • 左闭右闭区间 [left, right]
  • 左闭右开区间 [left, right)

这两种写法的区别主要体现在 while 循环的条件和边界的更新方式上。


1. 左闭右闭区间 [left, right]

思路

  • 查找区间包含 leftright,即 left <= right
  • 每次循环都判断中间值 mid 是否等于目标值。
  • 如果目标值比中间值小,右边界收缩为 mid - 1
  • 如果目标值比中间值大,左边界收缩为 mid + 1

代码实现

function binarySearch(nums, target) {
    let left = 0, right = nums.length - 1;
    while (left <= right) { // 注意等号
        let mid = left + ((right - left) >> 1); // 防止溢出
        if (nums[mid] > target) {
            right = mid - 1; // 去左区间
        } else if (nums[mid] < target) {
            left = mid + 1; // 去右区间
        } else {
            return mid; // 找到目标
        }
    }
    return -1; // 没找到
}

通俗解释

想象你在一本有序的字典里查单词,每次都翻到中间那一页。如果目标单词比中间的单词靠前,就只看前半本;如果靠后,就只看后半本。每次都把查找范围缩小一半,直到找到为止。


2. 左闭右开区间 [left, right)

思路

  • 查找区间包含 left,但不包含 right,即 left < right
  • 右边界初始化为 nums.length,而不是 nums.length - 1
  • 如果目标值比中间值小,右边界收缩为 mid
  • 如果目标值比中间值大,左边界收缩为 mid + 1

代码实现

function binarySearch(nums, target) {
    let left = 0, right = nums.length;
    while (left < right) { // 注意没有等号
        let mid = left + ((right - left) >> 1);
        if (nums[mid] > target) {
            right = mid; // 去左区间
        } else if (nums[mid] < target) {
            left = mid + 1; // 去右区间
        } else {
            return mid; // 找到目标
        }
    }
    return -1; // 没找到
}

通俗解释

还是查字典的例子,只不过这次你每次查找的区间是“左边包含,右边不包含”。这样写的好处是有些题目更容易处理边界问题。


三、两种写法的区别和选择

  • 左闭右闭:区间两端都包含,循环条件是 left <= right,右边界更新为 mid - 1
  • 左闭右开:区间只包含左端,循环条件是 left < right,右边界更新为 mid

两种写法本质一样,选哪种都可以,关键是要理解区间的含义,写代码时保持一致,不要混用。


四、总结

二分查找是算法的基础,掌握两种区间写法能让你在刷题和面试中游刃有余。记住:区间的定义决定了循环条件和边界更新方式。多写多练,理解透彻,算法基础就稳了!