Leetcode-35. 搜索插入位置

35. 搜索插入位置

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

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

示例 1:

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

解法一

可以顺序搜索查找,比当前大就往下遍历,比当前小就返回当前的index,最后返回数组长度(即插在最后一个index的后面)

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        for (int i = 0; i < nums.size(); ++i) {
            if (target > nums[i]) {
                ;
            } else {
                return i;
            }
        }
        return nums.size();
    }
};

解法二

可以二分查找,但二分查找虽然时间复杂度低一些,但是中间需要考虑的边界条件多一些,有两个地方需要考虑

  • 搜索到边界时需要退出并返回边界(插在最后一个位置后面)。
  • 当搜索到的start和end相邻时,mid为start,如果此时nums[mid]<target,则正常逻辑start更新为mid,则导致无限循环。

所以代码中需着重考虑这两点

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

但这样的思考显然过于复杂,写二分查找也不通用,所以看了一个题解后掌握了一个重要的思想:从一个元素什么时候不是解开始考虑下一轮搜索区间是什么,也就是要注意搜索区间。由于mid的范围为[start, end), 但是我们搜索区间的范围是[start, end], 所以一开始 start=0, end=nums.size(), 这样不用担心mid越界的问题,也包含了所有解的空间。之后每次更新区间都要注意这个范围的意义和前面保持一致。

由于start和end都是根据mid来更新,所以mid不可能取到end,只有可能取到start。且由于mid的范围限制,循环时判断start == end时就应该退出并返回start。

更新时如果nums[mid]<target,那么搜索区间肯定不包含mid之前包括mid的部分,最小也是mid+1,所以本着搜索区间应该是[start, end]的原则,start更新为mid+1。

反之如果 nums[mid]>target,那么搜索区间有可能包含mid,所以end更新为mid。

如果相等,则返回mid即可。

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int start = 0;
        int end = nums.size();
        while (start != end) {
            int mid = (start + end) / 2;
            if (nums[mid] < target) {
                start = mid + 1;
            } else if (nums[mid] > target) {
                end = mid;
            } else {
                return mid;
            }
        }
        return start;
    }
};
原文地址:https://www.cnblogs.com/eggplant-is-me/p/13984661.html