二分查找专题
主要解题思路:迭代法、递归法。迭代一般性能更好、占用存储较小,递归则书写方便
二分查找(简单)
- 思路一:迭代法,需要左、右两个指针。解题注意跳出循环的条件,和返回值(比如可以返回左、右边界值,或中间值)
var search = function(nums, target) {
let left = 0, right = nums.length - 1
// 左指针在右指针左边
while (left <= right) {
let mid = Math.floor((left + right) / 2)
if (nums[mid] === target) return mid
nums[mid] < target ? left = mid + 1 : right = mid - 1
}
return -1
};
- 思路二:递归法。
var search = function(nums, target) {
let left = 0, right = nums.length - 1
let dichotomy = (nums, left, right, target) => {
if (left > right) return -1
let mid = Math.floor((left + right) / 2)
if (nums[mid] === target) return mid
if (nums[mid] < target) {
return dichotomy(nums, mid + 1, right, target)
} else {
return dichotomy(nums, left, mid - 1, target)
}
}
return dichotomy(nums, left, right, target)
};
搜索插入位置(简单)
- 思路:迭代法。返回值有个巧妙之处
var searchInsert = function(nums, target) {
let left = 0, right = nums.length - 1
while (left <= right) {
let mid = Math.floor((right - left) / 2) + left
nums[mid] < target ? left = mid + 1 : right = mid - 1
}
return left
};
寻找峰值
- 思路:常规递归法。注意边界判断
var findPeakElement = function(nums) {
let n = nums.length
if (n === 1 || n === 0) return 0
if (nums[0] > nums[1]) return 0
if (nums[n - 1] > nums[n - 2]) return n - 1
for (let i = 1, j = n - 2; i <= Math.floor((n - 1) / 2); i++, j--) {
if (nums[i] > nums[i - 1] && nums[i] > nums[i + 1]) return i
if (nums[j] > nums[j - 1] && nums[j] > nums[j + 1]) return j
}
};
搜索旋转排序数组
- 思路:
- 迭代法。判断情况稍微复杂一点,首先要搞清,旋转后的数组,最大值 x 在中某处,以 x 分割的左右两部分,左边的所有值都大于右边的值。
- 现做如下分析:如果当前值与目标值相等,返回;如果当前值大于右边界(说明在左边),则再判断当前值是否大于目标值且目标值大于右边界(目标值也在左边),是则缩小右边界,否则缩小左边界;同理,如果当前值小于右边界(说明在右边)…
var search = function(nums, target) {
if (!nums.includes(target)) return -1
let left = 0, right = nums.length - 1
while (left <= right) {
if (nums[right] === target) return right
let mid = Math.floor((left + right) / 2)
if (nums[mid] === target) return mid
// 如果当前值在左边
if (nums[mid] > nums[right]) {
// 如果当前值大于目标值,且目标值在左边,缩小右边界
if (nums[mid] > target && target > nums[right]) {
right = mid - 1
} else {
left = mid + 1
}
} else {
// 如果当前值小于目标值,且目标值在右边,缩小左边界
if (nums[mid] < target && target < nums[right]) {
left = mid + 1
} else {
right = mid - 1
}
}
}
};
如果觉得对你有帮助的话,点个赞呗~
反正发文又不赚钱,交个朋友呗~
如需转载,请注明出处foolBirdd