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

二分搜索是一种高效的搜索算法,可以在有序数组中查找特定元素。寻找左侧边界的二分搜索是一种变体,它可以找到第一个等于目标值的元素的位置。如果数组中不存在目标值,则返回-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),比线性搜索更快。然而,该算法需要数组是有序的,如果数组无序,则需要先进行排序,这会增加时间复杂度。此外,该算法只适用于静态数组,如果数组需要频繁插入或删除元素,则需要使用其他数据结构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是Java中实现二分搜索算法的示例: ```java public class BinarySearch { public static int binarySearch(int[] arr, int target) { int left = 0; int right = arr.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == target) { return mid; } else if (arr[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; } public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int target = 6; int result = binarySearch(arr, target); if (result == -1) { System.out.println("Element not found"); } else { System.out.println("Element found at index " + result); } } } ``` 这个示例中,我们定义了一个`binarySearch`方法来执行二分搜索算法。该方法接受一个有序数组和目标元素作为参数,并返回目标元素在数组中的索引(如果存在),否则返回-1。 在`binarySearch`方法中,我们使用两个指针`left`和`right`来表示搜索范围的左右边界。然后,我们在每次迭代中计算中间元素的索引`mid`,并将其与目标元素进行比较。如果中间元素等于目标元素,则返回其索引。如果中间元素小于目标元素,则将左指针移到中间元素的右侧。如果中间元素大于目标元素,则将右指针移到中间元素的左侧。通过不断缩小搜索范围,最终可以找到目标元素或确定其不存在。 在示例的`main`方法中,我们创建了一个有序数组`arr`和一个目标元素`target`。然后,我们调用`binarySearch`方法来搜索目标元素,并根据返回的结果打印相应的消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

繁星召唤

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

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

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

打赏作者

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

抵扣说明:

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

余额充值