二分查找-边界处理问题梳理-JavaScript实现

96 阅读3分钟

今天回归了力扣的周赛,第一题完成之后,发现第二题是对第一题的性能优化。我的第一反应就是使用二分查找实现性能的优化。

二分查找的边界问题虽然以前已经搞清楚过,但是一段时间不用之后就又开始模糊了☠️,我决定写一篇文章,相当于是备忘录吧,记录一下二分查找的简单使用。(其实也是最近想尝试一下写博客来记录自己的学习之路😁)

边界问题

首先就是边界问题了,这边的边界指什么呢?

指的是leftright

注意:我所使用的方法是左闭右闭的方法

左闭右闭代表什么呢?

代表在查找的时候,left是可以取到的,right也是可以取到的。下面我写一下二分查找的一个经典模板,我会再重点的地方加上注释方便理解。

代码举例

下方代码的作用是,给定一个升序排序的nums数组,需要查找数组中是否target元素,有则返回其对应下标,没有则返回-1。 这道题其实就是力扣的第704题:leetcode.cn/problems/bi… 大家可以去练练手。

let left = 0
let right = nums.length - 1// 注意 此处数组的长度减去 1 是为了实现左闭右闭, 使得right可以取到,即nums[right]合法。

// 注意 下方while条件中,是要写 left <= right 还是 left < right 呢? 
//这个时候只需要思考我们的 "左闭右闭" 的查找范围中, left <= right 的情况是否是合法的。
//比如我取一个数组的范围是 "[3, 3]" 这代表我取数组的下标为3的元素,这明显是符合条件的。
//所以此处需要写left <= right
while (left <= right) {
    let mid = Math.floor((left + right) / 2)
    if (nums[mid] > target) {
        // 注意 此处为什么不是 right = mid 呢?
        // 因为我们的边界是左闭右闭的,所以在上次查找的时候,边界也是查找的范围,已经被查找过了
        // 所以我们这个时候直接略去mid即可,下面的一个 else if 分支也是同理的
        right = mid - 1
    } else if (nums[mid] < target) {
        left = mid + 1
    } else {
        return mid
    }
}
return -1

总结

下面总结一下全部的内容,以后如果记忆模糊了可以直接看下面的内容✌️✌️

  • 将搜索范围设置成左闭右闭
  • while 循环内的条件设置成left <= right,因为在左闭右闭的范围中进行搜索,类似于[3, 3]的搜索范围是合理的,它代表范围是下标为3的元素。
  • while 循环内的 if 判断中,当出现nums[mid] > target的情况下,需要将执行的操作设置为right = mid - 1,原因是在左闭右闭的边界中,上一轮的查询已经将mid也放入了查询的范围中了,没有必要将mid对应的下标再放入下一轮的查询中。

希望以上的内容对你有所帮助。😉