【leetcode】35.搜索插入位置

79 阅读2分钟

leetcode-35.png

二分查找,很基础,但是细节又特别多。

二分查找,不难,看着就会,上手就懵逼,细节处理不到位就不能ac。
关于while条件中的,left < right,还是 left <= right,都会影响后续的处理

left <= right

这里主要是看right的边界问题,这里的right处于闭合状态,也就是[left, right],左右闭合,此时在while内部的逻辑中,right也应该是处于闭合的状态,上一轮的mid已经检测过了的地方,此时不应该再检测,所以应该为right = mid - 1

var searchInsert = 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
        } else if (nums[mid] > target) {
            right = mid - 1
        } else {
            left = mid + 1
        }
    }
    return left
};

先说上面这个代码,条件是 left <= right
这里的跳出条件为 left = right + 1
所以这里更适用于查找具体的数字,以及要插入的位置。

[1,2,3,5,6] target = 4时
left = 0, right = 4,mid = 2,nums[mid] = 3
left = mid + 1 = 3,right = 4,mid = 3,nums[mid] = 5
left = 3, right = mid - 1 = 2,此时直接不满足条件,直接跳出循环
返回left = 3

  • 在每次循环中,left 和 right 都可能移动到对方的位置。
  • 循环终止时,left 刚好超出 right 一位,即 left = right + 1
  • 适用于需要在循环内明确找到目标值在其不存在时返回插入位置的情况。

left < right

这里是左闭右开,也就是[left, right),此时right所在的地方是没有值的,所以在while内的逻辑中,检测过后的right的范围也应该是在mid的位置,这样保证不会漏掉

var searchInsert = function(nums, target) {
    let left = 0, right = nums.length;
    while (left < right) {
        let mid = Math.floor((left + right) / 2);
        if (nums[mid] === target) {
            return mid;
        } else if (nums[mid] > target) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return left;
};
  • 查找目标值是否存在:用于需要检查目标值是否存在但不关心其具体位置的情况。
  • 查找边界位置:用于寻找特定条件下的边界位置,如最左边或最右边符合条件的位置。

特点

  • 在每次循环中,left 和 right 不会相互越界,即使在最后一次循环时也是如此。
  • 循环终止时,left 和 right 相等,即 left = right
  • 适用于寻找满足特定条件的边界位置。