JavaSctipt算法——二分查找

131 阅读2分钟

这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

分不清东南西北,只知道梦想是远方 —— 我是小晨,今天来聊一下二分查找

什么是二分查找?

在计算机科学领域,二分查找(Binary Search) 是一种查找算法(也称折半查找),用来在一个数组中查找指定的元素。注意这个数组需要是一个有序数组才有效。二分查找优于标准的线性查找(Linear Search),因为它查找速度更快,效率更高。

这种算法不是在一个for循环中依次按照索引0,1,2,3,4这样查找,它的具体做法是每次把查找范围缩小一半,直到找到目标值。

速度快

  1. 如果是普通遍历,查找100个规模,最坏情况需要 100 次.
  2. 经过二分查找,最坏只需要 7 次. 

100个元素-->50-->25-->13-->7-->4-->2-->1

  1. 速度大大提升, ok 直接上题:

原题链接:二分查找来源力扣(LeetCode)

/*给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  
 *写一个函数搜索 nums 中的 target
 *如果目标值存在返回下标,否则返回 -1。
*/
//题目 二分查找
/**
 * @param {number[]} nums: [-1,0,3,5,9,12]
 * @param {number} target: 3
 * @return {number}
 */
var search = function(nums, target) {

};

过程解析

解析过程中以下面代码为例:

 let arr = [1, 2, 3, 6, 4, 8, 9, 10]
  • 在执行查找操作时需要把3个数据保存为变量:minText, lenmaxTextminText初始值为0

  • MaxText 的值可以由数组的长度计算得到:let maxIndex = nums.length - 1;

  • 我们用minTextMaxText 的值相加,然后除以 2 可以得到 len 的初始值。

  • 问题是这个值可能不是一个整数,可以用 Math.floor() 或者 Math.ceil() 或者parseInt()来得到临近的整数,这里我们用 parseInt()let len = parseInt((MaxText + minText) / 2)。我们的while循环会一直运行直到结束。这里可以用 while(minText <= maxText)

  • 比如数组里一共有9个元素,根据上述的计算规则。len = parseInt(( 0 + 8) / 2),得到值为 4。我们选取数组中索引为4的元素4,。现在我们会用这个值和目标值“8”进行比较,看看它更大还是更小。如果len 所在的值比目标值8小,我们知道目标值可能存在于len的右侧。然后把len的值调整为len右侧的那个索引。

  • 如果len 所在的值大于目标值8,我们知道目标值可能存在于len 的左侧。然后把 maxText 调整为 len 左侧的那个索引。如果len所在的值恰好等于目标值8,那么我们就顺利找到了目标值,把这个len值返回即可。这个while循环可能只会执行一次,也有可能会执行很多次,取决于这个数组的长度。最后如果没有找到目标值,我们返回 -1 表示没有找到指定的值。

我们会在数组中间的元素作为len元素,然后把它的值和目标值进行比对。根据目标值是大于还是小于len元素,我们可以从数组中排除左侧或者右侧的元素。

/*给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  
 *写一个函数搜索 nums 中的 target
 *如果目标值存在返回下标,否则返回 -1。
*/
//题目 二分查找
/**
 * @param {number[]} nums: [-1,0,3,5,9,12]
 * @param {number} target: 3
 * @return {number}
 */
    var search = function (nums, target) {
     if (!nums.length) {
        return -1;
      }
      let minText = 0, maxText = nums.length - 1, len;
      while (minText < maxText) {
        len = minText + Math.floor((maxText - minText) / 2);
        if (nums[len] == target) {
          return len;
        } else if (nums[len] < target) {
          minText = len + 1;
        } else if (nums[len] > target) {
          maxText = len - 1;
        }
      }
      return nums[minText] == target ? minText : -1;
    };

最后

我是小晨,一个不想加班的加班族。