二分查找:
搜索一个数,存在则返回索引,不存在则返回-1:
- 注意的点在于
left<right
是因为right=nums.length
。- 搜索区间是在 [left,right) 。
- 如果是
left<=right
,则right = nums.length-1
。(搜索区间则在 [left,right])
- 使用
Math.floor
是为了解决溢出的问题 right = mid
,而不是mid-1
- 因为right这里取值是
nums.length
,当没找到目标值的时候,是去 [left,mid] 或者 [mid+1,right) 里寻找。 - 如果取值是
num.length-1
的话,则取 [left,mid -1 ] 或者 [mid+1 , right] 中寻找。
- 因为right这里取值是
var search = function (nums, target) {
let left = 0, right = nums.length;
while (left < right) {
let mid = Math.floor((right - left) / 2) + left;
if (nums[mid] == target) return mid;
else if (nums[mid] < target) left = mid + 1;
else right = mid;
}
return -1;
};
寻找左侧边界的二分搜索:
关键点在于: if (nums[mid] == target) right = mid;
,不再是直接return mid了;
- 当寻找到目标值的时候,不马上返回而是压缩right,使得区间不断向左收缩,在 [left,mid)里继续搜索。
// 寻找左侧边界
var searchLeft = function (nums, target) {
let left = 0, right = nums.length;
while (left < right) {
let mid = Math.floor((right - left) / 2) + left;
if (nums[mid] == target) right = mid;
else if (nums[mid] < target) left = mid + 1;
else right = mid;
}
return nums[left] == target ? left : -1;
};
let nums = [5, 7, 7, 8, 8, 10], target = 8;
console.log(searchLeft(nums, target)); //3
寻找右测边界的二分搜索:
// 寻找右侧边界
var searchRight = function (nums, target) {
let left = 0, right = nums.length;
while (left < right) {
let mid = Math.floor((right - left) / 2) + left;
if (nums[mid] == target) left = mid + 1;
else if (nums[mid] < target) left = mid + 1;
else right = mid;
}
// 减一的原因:对 left 的更新必须是 left = mid + 1,循环结束后nums[left - 1]才有可能是 target
return nums[left - 1] == target ? (left - 1) : -1;
};