35. 搜索插入位置(C++)

题目

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

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

示例 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

分析与题解

暴力解法

从数组的左边遍历到右边,如果遇到相等的元素,直接返回下标;如果遇到第 1 个严格大于 target 的元素,返回这个元素的下标;如果数组里所有的元素都严格小于 target,返回数组的长度 len。

代码如下:

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
    	//num记录是否出现了首位比target大的元素
        int num = 0;
        int tmp = 0;
        for(int i=0;i<nums.size();i++){
            if(nums[i]==target)
                return i;
            if(nums[i]>target && num==0){
                tmp = i;
                num = 1;
            }
        }
        if(num==0)
            return nums.size();
        else
            return tmp;
    }
};

二分查找

在有序数组中查找插入元素的位置,显然可以使用二分查找。提供的思路是「排除法」,思路是:在循环的过程中,不断排除不需要的解,最后剩下的那个元素的位置就一定是插入元素的位置。

具体来说:

  • 首先,插入位置有可能在数组的末尾,需要单独判断,此时返回数组的长度;
  • 否则,根据示例和暴力解法的分析,插入的位置是大于等于 target 的第 1 个元素的位置。

因此,严格小于 target 的元素一定不是解,在循环体中将左右边界 left 和 right 逐渐向中间靠拢,最后 left 和 right 相遇,则找到了插入元素的位置。根据这个思路,可以写出如下代码。

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int len = nums.size();
        //考虑数组为空的特殊情况
        if(len==0)
            return 0;
        //考虑数据所有元素小于target的情况
        if(nums[len-1]<target)
            return len;
        
        int left = 0;
        int right = len-1;
        while(left<right){
            int mid = left + (right - left)/2;
            //当nums[mid]严格小于目标元素时,肯定不是解
            if(nums[mid]<target){
                //下轮搜索区间 [mid + 1 , right]
                left = mid + 1;
            } else {
                //搜索区间为上轮的反面 [left, mid]
                right = mid;
            }
        }
        return left;
    }
};

注意代码是左动,所以中间值不需要进行变动,进行下取整即可。

posted @ 2020-08-25 17:25  脱线森林`  阅读(218)  评论(0编辑  收藏  举报