【近日力扣】(二分法合集1)二分查找+搜索插入位置+寻找峰值+搜索旋转排序数组

二分查找专题
主要解题思路:迭代法、递归法。迭代一般性能更好、占用存储较小,递归则书写方便

二分查找(简单)

  • 思路一:迭代法,需要左、右两个指针。解题注意跳出循环的条件,和返回值(比如可以返回左、右边界值,或中间值)
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值