You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用二分查找在有序数组中筛选指定范围的数字?

有序数组范围查询的二分查找问题修复与优化

一、修复死循环问题

你的代码中二分查找陷入死循环的核心原因是:当start和end相邻时,mid取Math.floor((start+end)/2)会等于start,此时如果满足sortedArray[mid] < target,赋值start = mid后,start和end的关系没有变化,循环无法推进,最终卡死。

我们可以通过调整二分查找的边界定义和循环逻辑来解决这个问题,同时更精准地匹配需求:

  • 左边界:找到第一个大于等于范围下限的元素索引
  • 右边界:找到第一个大于范围上限的元素索引

这样利用数组的slice方法(左闭右开特性),直接截取两个边界之间的元素即可得到结果。

修正后的二分查找函数及最终实现:

// 查找第一个大于等于target的元素索引
function findFirstGreaterOrEqual(arr, target) {
  let start = 0, end = arr.length; // end初始为数组长度,兼容所有元素都小于target的情况
  while (start < end) {
    const mid = Math.floor((start + end) / 2);
    if (arr[mid] >= target) {
      end = mid;
    } else {
      start = mid + 1;
    }
  }
  return start;
}

// 查找第一个大于target的元素索引
function findFirstGreaterThan(arr, target) {
  let start = 0, end = arr.length;
  while (start < end) {
    const mid = Math.floor((start + end) / 2);
    if (arr[mid] > target) {
      end = mid;
    } else {
      start = mid + 1;
    }
  }
  return start;
}

function getNumsWithin(array, range) {
  const [lower, upper] = range;
  const leftIdx = findFirstGreaterOrEqual(array, lower);
  const rightIdx = findFirstGreaterThan(array, upper);
  return array.slice(leftIdx, rightIdx);
}

测试验证:

getNumsWithin([1,2,3,5,6,7], [3.3, 6.7]); // [5, 6]
getNumsWithin([1,2,3,5,6,7], [6, 7]); // [6, 7]
getNumsWithin([1,2,3,5,6,7], [8, 10]); // []

二、关于一次查找确定两个索引的问题

无法通过一次二分查找同时确定起始和结束索引。因为二分查找的核心是针对单个目标值进行边界定位,而我们需要定位的是两个独立的目标(范围下限和上限),必须通过两次独立的二分查找来分别获取左、右边界。

不过你可以将两次查找逻辑封装在同一个函数内,减少代码分散,但本质上还是两次二分过程。

内容的提问来源于stack exchange,提问作者Joji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 08:45:49