【算法】寻找左侧边界的二分搜索

二分搜索是一种高效的搜索算法,可以在有序数组中查找特定元素。寻找左侧边界的二分搜索是一种变体,它可以找到第一个等于目标值的元素的位置。如果数组中不存在目标值,则返回-1。该算法的基本思想是在每次迭代中将搜索范围缩小一半,直到找到目标元素或搜索范围为空为止。在寻找左侧边界时,如果中间元素等于目标值,则继续在左半部分搜索,否则在右半部分搜索。如果中间元素大于目标值,则在左半部分搜索,否则在右半部分搜索。这样可以保证最终找到的位置是第一个等于目标值的元素的位置。

// 这种方式取的区间是[left, right),即左闭右开区间
function leftBound1(nums, target) {
  if (nums.length === 0) {
    return -1;
  }
  let left = 0;
  let right = nums.length - 1;

  // 此时终止条件式left == right
  // 每次循环的搜索区间是 [left, right)
  while (left < right) {
    let mid = parseInt((left + right) / 2, 10);
    if (nums[mid] === target) {
      // 该算法能够搜索左边界的原因是其在遇到nums[mid] == target时不会立即返回,而是缩小区间的上届right,在区间[left,right)中继续搜索,即不断向左收缩,达到锁定左侧边界的目的
      right = mid;
    } else if (nums[mid] < target) {
      left = mid + 1;
    } else if (nums[mid] > target) {
      right = mid;
    }
  }

  // 如果target比所有数都大,此时返回的索引将会是nums.length则证明没找到,返回-1
  if (left === nums.length) {
    return -1;
  }

  // 如果找到的数比所有的都小,将会返回索引为0,此时需要进行判断索引为0时是否是target值
  return nums[left] === target ? left : -1;
}

const nums = [1, 2, 2, 2, 3];
const target = 2;
console.log(leftBound1(nums, target));

// 这种方式取得区间是[left,right]
function leftBound2(nums, target) {
  let left = 0;
  let right = nums.length - 1;

  while (left <= right) {
    const mid = parseInt((left + right) / 2, 10);

    if (nums[mid] === target) {
      right = mid - 1;
    } else if (nums[mid] > target) {
      right = mid - 1;
    } else if (nums[mid] < target) {
      left = mid + 1;
    }
  }
  if (left >= nums.length || nums[left] !== target) {
    return -1;
  }
  return left;
}

const nums2 = [1, 2, 2, 2, 3];
const target2 = 2;
console.log(leftBound2(nums2, target2));

该算法的时间复杂度为O(log n),比线性搜索更快。然而,该算法需要数组是有序的,如果数组无序,则需要先进行排序,这会增加时间复杂度。此外,该算法只适用于静态数组,如果数组需要频繁插入或删除元素,则需要使用其他数据结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁星召唤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值