35. 搜索插入位置

35. 搜索插入位置

题目:35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:
输入: [1,3,5,6], 5
输出: 2

示例 2:
输入: [1,3,5,6], 2
输出: 1

示例 3:
输入: [1,3,5,6], 7
输出: 4

示例 4:
输入: [1,3,5,6], 0
输出: 0

思路

本题的要求是查找到目标值在数组中的位置,如果不存在,返回它将会被顺序插入的位置。所以套用二分算法的模板即可。

代码

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int n = nums.size();
        int l = 0, r = n;
        while (l < r) {
            int mid = l + (r - l) / 2;
            if (target > nums[mid]) {
                l = mid + 1; 
            } else if (target < nums[mid]) {
                r = mid;
            } else if (target == nums[mid]) {
                r = mid;    
            }
        }  
        return l;
    }
};

优化

二分算法很简单,但细节是魔鬼。

从下面几点解释其他版本的代码与上述代码的区别:

  1. 为什么 r = n,r = n - 1 不行吗

这是由于 while 循环体内的条件决定的,l < r 就意味着搜索区间是左闭右开区间。因此如果使 r = n - 1,代码会产生一个小 bug 。即示例3所示,当 target > nums[n - 1] 时,由于搜索区间的限制,无法返回 n

所以可以在开始的地方加入判断,即可解决此 bug

if(target > nums[n - 1]) return n;
  1. while 中的判断条件是 \(l <= r\) 可以吗

可以,此时搜索区间就是左闭右闭区间。习惯来说,使用 \(l < r\) 从搜索区间中排查元素,结束循环后再进行检查。而 \(l<=r\) 则是从搜索区间中查找元素,遇到符合条件的直接返回。

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int n = nums.size();
        int l = 0, r = n - 1;
        while (l <= r) {
            int mid = l + (r - l) / 2;
            if (target > nums[mid]) {
                l = mid + 1; 
            } else if (target < nums[mid]) {
                r = mid - 1;
            } else if (target == nums[mid]) {
                return mid;   
            }
        }  
        return l;
    }
};
posted @ 2021-02-22 21:01  snakeee  阅读(49)  评论(0)    收藏  举报