二分查找是非常基础的查找算法,相较于传统的遍历O(n)的时间复杂度,二分查找的时间复杂度为O(logn)。学习二分查找的意义和应用场景就是在于当数组是有序的时候,我们应尽量地去使用二分查找去代替传统的遍历,可以提高一定的算法时间复杂度。
下面是二分查找最基本的case.
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var search = function (nums, target) {
let left = 0, right = nums.length - 1
// 熟练了可以固定用这套规则 <= 和 const mid = Math.floor((left + right) / 2)
while (left <= right) {
const mid = Math.floor((left + right) / 2)
if (nums[mid] > target) {
right = mid - 1
} else if (nums[mid] < target) {
left = mid + 1
} else {
return mid
}
}
return -1
};
有了二分查找的思想和基础算法模板之后,我们还可以解决哪些题目呢?
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
let left = 0, right = nums.length - 1
while(left <= right) {
const mid = Math.floor((left + right) / 2)
if(nums[mid] === target) {
return mid
} else if(nums[mid] > target) {
right = mid - 1
} else {
left = mid + 1
}
}
// 数组中不存在target,相对位置:right, left
return left // left为待插入位置
};
34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var searchRange = function (nums, target) {
let resBeginIndex = -1, resEndIndex = -1
// 思路:两次二分查找
let left = 0, right = nums.length - 1
while (left <= right) {
const mid = Math.floor((left + right) / 2)
if (nums[mid] === target) {
resBeginIndex = mid
right = mid - 1
} else if (nums[mid] > target) {
right = mid - 1
} else {
left = mid + 1
}
}
left = 0, right = nums.length - 1
while (left <= right) {
const mid = Math.floor((left + right) / 2)
if (nums[mid] === target) {
resEndIndex = mid
left = mid + 1
} else if (nums[mid] > target) {
right = mid - 1
} else {
left = mid + 1
}
}
return [resBeginIndex, resEndIndex]
};
/**
* @param {number} x
* @return {number}
*/
var mySqrt = function (x) {
// 二分查找
let left = 0, right = x
while (left <= right) {
const mid = Math.floor((left + right) / 2)
const multiRes = mid * mid
if (multiRes === x) {
return mid
} else if (multiRes > x) {
right = mid - 1
} else {
left = mid + 1
}
}
// 相对位置right left
return right
};
/**
* @param {number} num
* @return {boolean}
*/
var isPerfectSquare = function (num) {
let left = 0, right = num
while (left <= right) {
const mid = Math.floor((left + right) / 2)
const multiRes = mid * mid
if (multiRes === num) {
return true
} else if (multiRes > num) {
right = mid - 1
} else {
left = mid + 1
}
}
return false // 不存在,则返回false
};