数组/二分查找|算法笔记系列01

29 阅读2分钟

二分查找|TypeScript 代码笔记

题目还原

自己回忆:

给定一个不含有重复元素的有序数组(升序/降序),给定一个target值。请使用log(n)时间复杂度的一个函数,获取该数组中等于target值的元素的下标。如果没找到,则返回-1

LeetCode:

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果 target 存在返回下标,否则返回 -1

你必须编写一个具有 O(log n) 时间复杂度的算法。

思路分析

使用二分查找解题:给定一个区间,获取该区间中间位置的值。经过大小比较后,将区间减半。临界条件就是区间不存在时。

解题的关键在于:如何定义区间

给出两种定义区间的范式: [left, right][left, right)

代码解答

第一种: target 所在区间为[left, right]

const binarySearch1 = (nums: Array<number>, target: number): number => {
  // 起始区间: [0, length - 1]
  let left = 0;
  let right = nums.length - 1;

  while (left <= right) {
    // 取等号, 因为[left, left]有意义
    const mid = Math.floor((left + right) / 2);
    const val = nums[mid];

    if (target > val) {
      // target 在右区间, 所以区间变为[mid, right]. 
      // 【端点讨论(检验/舍值)】因为 mid 处不成立, 所以区间变为[mid + 1, right]
      left = mid + 1;
    } else if (target < val) {
      // target 在左区间, 所以区间变为[left, mid]. 
      // 【端点讨论(检验/舍值)】因为 mid 处不成立, 所以区间变为[left, mid - 1]
      right = mid - 1;
    } else {
      // val === target, 返回val的下标
      return mid;
    }
  }

  // 区间不存在了, 证明没查找到, 返回-1
  return -1;
};

第二种: target 所在区间为[left, right)

const binarySearch2 = (nums: Array<number>, target: number): number => {
  // 起始区间: [0, length)
  let left = 0;
  let right = nums.length;

  while (left < right) {
    // 不取等号, 因为[left, left)没有意义
    const mid = Math.floor((left + right) / 2);
    const val = nums[mid];

    if (target > val) {
      // target 在右区间, 所以区间变为[mid, right).
      // 【端点讨论(检验/舍值)】 因为mid处不成立, 所以区间变为[mid + 1, right)
      left = mid + 1;
    } else if (target < val) {
      // target 在左区间, 所以区间变为[left, mid).
      // 【端点讨论(检验/舍值)】因为mid处不成立, 所以区间就是[left, mid)
      right = mid;
    } else {
      return mid;
    }
  }

  return -1;
};

两个代码均跑通✅,运行结果:

image.png