二分查找|TypeScript 代码笔记
题目还原
自己回忆:
给定一个不含有重复元素的有序数组(升序/降序),给定一个target值。请使用log(n)时间复杂度的一个函数,获取该数组中等于target值的元素的下标。如果没找到,则返回-1。
LeetCode:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果 target 存在返回下标,否则返回 -1。
你必须编写一个具有 O(log n) 时间复杂度的算法。
思路分析
使用二分查找解题:给定一个区间,获取该区间中间位置的值。经过大小比较后,将区间减半。临界条件就是区间不存在时。
解题的关键在于:如何定义区间
给出两种定义区间的范式: [left, right]和[left, right)。
代码解答
第一种: target 所在区间为[left, right]
const binarySearch1 = (nums: Array<number>, target: number): number => {
// 起始区间: [0, length - 1]
let left = 0;
let right = nums.length - 1;
while (left <= right) {
// 取等号, 因为[left, left]有意义
const mid = Math.floor((left + right) / 2);
const val = nums[mid];
if (target > val) {
// target 在右区间, 所以区间变为[mid, right].
// 【端点讨论(检验/舍值)】因为 mid 处不成立, 所以区间变为[mid + 1, right]
left = mid + 1;
} else if (target < val) {
// target 在左区间, 所以区间变为[left, mid].
// 【端点讨论(检验/舍值)】因为 mid 处不成立, 所以区间变为[left, mid - 1]
right = mid - 1;
} else {
// val === target, 返回val的下标
return mid;
}
}
// 区间不存在了, 证明没查找到, 返回-1
return -1;
};
第二种: target 所在区间为[left, right)
const binarySearch2 = (nums: Array<number>, target: number): number => {
// 起始区间: [0, length)
let left = 0;
let right = nums.length;
while (left < right) {
// 不取等号, 因为[left, left)没有意义
const mid = Math.floor((left + right) / 2);
const val = nums[mid];
if (target > val) {
// target 在右区间, 所以区间变为[mid, right).
// 【端点讨论(检验/舍值)】 因为mid处不成立, 所以区间变为[mid + 1, right)
left = mid + 1;
} else if (target < val) {
// target 在左区间, 所以区间变为[left, mid).
// 【端点讨论(检验/舍值)】因为mid处不成立, 所以区间就是[left, mid)
right = mid;
} else {
return mid;
}
}
return -1;
};
两个代码均跑通✅,运行结果: