二分法(Binary Search)适用于 有序 或 单调性(单调递增/递减) 的问题,它可以 快速 缩小搜索范围,时间复杂度为 O(log n),比线性查找 O(n) 更高效。
📌 适用场景
✅ 1. 在有序数组/列表中查找元素
如果数组是 升序 或 降序 排列的,可以使用二分查找快速找到目标值。
function binarySearch(arr, target) {
let left = 0, right = arr.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (arr[mid] === target) return mid;
if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1; // 没找到
}
console.log(binarySearch([1, 3, 5, 7, 9], 5)); // 输出 2
console.log(binarySearch([1, 3, 5, 7, 9], 6)); // 输出 -1
✅ 2. 处理“最接近”或“最小满足条件”的问题
比如 “求最小的 x,使得 f(x) 满足某个条件”,可用 二分答案 来优化搜索。
示例:寻找数组中 ≥ target 的最小元素
function lowerBound(arr, target) {
let left = 0, right = arr.length;
while (left < right) {
let mid = Math.floor((left + right) / 2);
if (arr[mid] >= target) right = mid;
else left = mid + 1;
}
return left;
}
console.log(lowerBound([1, 3, 5, 7, 9], 6)); // 输出 3 (索引 3 处是 7)
✅ 3. 处理最大值/最小值优化问题
当一个函数 f(x)
在区间 [left, right]
内 单调递增/递减,可以用二分查找最优解。
示例:最小长度的子数组(优化 O(n log n))
可以用二分优化 minSubArrayLen
(之前用滑动窗口 O(n))。
var minSubArrayLen = function(target, nums) {
let prefixSum = [0];
for (let num of nums) prefixSum.push(prefixSum[prefixSum.length - 1] + num);
let ans = Infinity;
for (let i = 0; i < nums.length; i++) {
let left = i + 1, right = nums.length, best = -1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (prefixSum[mid] - prefixSum[i] >= target) {
best = mid;
right = mid - 1;
} else left = mid + 1;
}
if (best !== -1) ans = Math.min(ans, best - i);
}
return ans === Infinity ? 0 : ans;
};
🚫 二分法不适用的情况
❌ 1. 无法定义单调关系
如果数据没有 单调递增/递减 规律,二分法无法缩小范围。例如:
- 查找 无序数组 中的元素(需要
O(n)
遍历) - 解决 背包问题、组合问题(需要
DFS
或DP
)
❌ 2. 目标数据动态变化
如果数据在查找过程中不断变化(如流式数据、在线搜索),二分法通常不适用。
🔹 总结
二分法适用于: ✅ 已排序的数组(经典查找)
✅ 满足单调性的函数/问题(二分答案)
✅ 求解“最小满足”或“最大满足”条件的问题
不适用于: ❌ 无序数据(找不到规律)
❌ 数据动态变化(二分范围会失效)