# 二分搜索
比较次数: 0
# 算法原理
二分搜索(Binary Search)是一种高效的搜索算法,它利用数据的有序性,通过将搜索范围逐步缩小一半来定位目标元素。每次比较中间元素与目标值,根据比较结果决定在哪一半继续搜索,直到找到目标元素或确定元素不存在。
# 算法步骤
- 确保数组已经排序
- 设置左边界left = 0和右边界right = length - 1
- 当left <= right时,重复以下步骤:
- 计算中间位置mid = (left + right) / 2
- 如果中间元素等于目标值,返回mid
- 如果中间元素大于目标值,在左半部分搜索,right = mid - 1
- 如果中间元素小于目标值,在右半部分搜索,left = mid + 1
- 如果未找到目标值,返回-1
# 代码实现
function binarySearch(arr, target) {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
// 避免整数溢出的写法
const mid = left + Math.floor((right - left) / 2);
if (arr[mid] === target) {
return mid; // 找到目标值
} else if (arr[mid] > target) {
right = mid - 1; // 在左半部分继续搜索
} else {
left = mid + 1; // 在右半部分继续搜索
}
}
return -1; // 未找到目标值
}
// 递归版本的二分搜索
function recursiveBinarySearch(arr, target, left = 0, right = arr.length - 1) {
if (left > right) {
return -1;
}
const mid = left + Math.floor((right - left) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] > target) {
return recursiveBinarySearch(arr, target, left, mid - 1);
} else {
return recursiveBinarySearch(arr, target, mid + 1, right);
}
}
# 复杂度分析
# 时间复杂度
- 最好情况:O(1),目标元素在中间位置
- 最坏情况:O(log n),需要多次折半
- 平均情况:O(log n)
# 空间复杂度
- 迭代版本:O(1)
- 递归版本:O(log n),由于递归调用栈的开销
# 算法特点
# 优点
- 时间复杂度低,效率高
- 适用于大规模数据搜索
- 实现简单,容易理解
# 缺点
- 要求数据必须有序
- 只适用于支持随机访问的数据结构(如数组)
- 对于小规模数据,可能不如线性搜索
# 适用场景
- 在大规模有序数据集中查找元素
- 需要频繁进行查找操作
- 数据集较为稳定,排序成本可以分摊
# 变体和应用
- 查找第一个等于目标值的元素
- 查找最后一个等于目标值的元素
- 查找第一个大于等于目标值的元素
- 查找最后一个小于等于目标值的元素
// 查找第一个等于目标值的元素
function searchFirstEqual(arr, target) {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
const mid = left + Math.floor((right - left) / 2);
if (arr[mid] > target) {
right = mid - 1;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
// 找到目标值,但需要确认是否为第一个
if (mid === 0 || arr[mid - 1] !== target) {
return mid;
}
right = mid - 1;
}
}
return -1;
}
// 查找第一个大于等于目标值的元素
function searchFirstGreaterEqual(arr, target) {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
const mid = left + Math.floor((right - left) / 2);
if (arr[mid] >= target) {
if (mid === 0 || arr[mid - 1] < target) {
return mid;
}
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
# 实际应用
- 在数据库索引中快速定位记录
- 在有序数组中进行快速查找
- 在二分图匹配中寻找最优解
- 在机器学习中的模型参数优化