「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」
百度百科:在计算机科学中,二分搜索(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。
可以说二分查找是一种非常高效的搜索算法
二分算法的基本结构
function binarySearch(arr, target) {
var left = 0,
right = ...
while (...) {
var mid = (left + right) >> 1
if (arr[mid] === target) {
...
}
else if (target < arr[mid]) {
...
}
else if (target > arr[mid]) {
...
}
}
return ...
}
基本的二分算法
寻找一个数
二分查找的裸题 704. 二分查找
function binarySearch (nums, target) {
if (!nums.length) return -1
var left = 0, right = nums.length - 1
while (left <= right) {
var mid = (left + right) >> 1
if (nums[mid] === target) return mid
else if (nums[mid] < target) left = mid + 1
else if (nums[mid] > target) right = mid - 1
}
return -1
};
//nums [-1,0,3,5,9,12]
//target 9
binarySearch(nums, target) // 4
思考一个问题:如果数组中存在相同的元素比如
[-1,0,3,3,5,9,12],需要寻找3此时是希望返回左侧的还是右侧下标的元素既2或3
寻找左侧边界
function left_binarySearch (nums, target) {
if (!nums.length) return -1
var left = 0, right = nums.length - 1
while (left < right) {
var mid = (left + right) >> 1
if (nums[mid] === target) right = mid
else if (nums[mid] < target) left = mid + 1
else if (nums[mid] > target) right = mid
}
return left
};
//nums [-1,0,3,3,5,9,12]
//target 3
left_binarySearch(nums, target) // 2
寻找右侧边界
function right_binarySearch (nums, target) {
if (!nums.length) return -1
var left = 0, right = nums.length - 1
while (left < right) {
var mid = (left + right) >> 1
if (nums[mid] === target) left = mid + 1
else if (nums[mid] < target) left = mid + 1
else if (nums[mid] > target) right = mid
}
return left - 1
};
//nums [-1,0,3,3,5,9,12]
//target 3
right_binarySearch(nums, target) // 3
小范围优化
function binarySearch (nums, target) {
if (!nums.length) return -1
var left = 0, right = nums.length - 1
while (right - left > 3) { // 如果左右小于3
var mid = (left + right) >> 1
if (nums[mid] === target) return mid
else if (nums[mid] < target) left = mid + 1
else if (nums[mid] > target) right = mid - 1
}
// 小范围循环
for (var i = left; i <= right; i++) {
if (numbs[i] === target) return i
}
return -1
};
//nums [-1,0,3,5,9,12]
//target 9
binarySearch(nums, target) // 4
二分算法应用
/**
* @param {number} c
* @return {boolean}
*/
var judgeSquareSum = function(c) {
if(c === 0) return true
for(var i = 0; i < Math.sqrt(c); i++) {
var left = i, right = Math.floor(Math.sqrt(c))
// 二分
while(left <= right) {
var mid = (left + right) >> 1
var rst = i*i + mid*mid
if(rst === c) return true
else if(rst < c) left = mid + 1
else if(rst > c) right = mid - 1
}
}
return false
};
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var searchRange = function (nums, target) {
var ret = [-1, -1]
ret[0] = binarySearch(nums, target)
if (ret[0] == nums.length || nums[ret[0]] != target) {
return [-1, -1]
}
ret[1] = binarySearch(nums, target + 1) - 1//查找第一个比target大的位置,前一位就是target结束位置。如果是最后一位返回 nums.length -1
return ret
};
// 查找第一个大于等于x的值
var binarySearch = function (nums, x) {
var head = 0,
tail = nums.length - 1,
mid
while (tail - head > 3) {
mid = (head + tail) >> 1
if (nums[mid] >= x) tail = mid
else head = mid + 1
}
for (var i = head; i <= tail; i++) {
if (nums[i] >= x) return i
}
return nums.length //最大长度下一位方便求值
}
--未完待续--