Leetcode35. 搜索插入位置——数组/二分查找法

发现自己刷完题后还是印象不深,痛定思痛,开始写题解了,从数组开始。刷题顺序参考了代码随想录

看完题后先用自己的方法尝试解决,因为是有序数组,常规思路解决其实也很容易。

遍历数组的每一个元素,找到大于等于target的数,就跳出循环,返回i值。如果都比target小,nums.size()就是插入的位置。

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

执行结果也还是可以的。

下面学习二分法

有序数组是二分查找的前提。

基础思路:先设定左侧下标 left 和右侧下标 right,再计算中间下标mid。每次根据 nums[mid] 和 target 之间的大小进行判断,相等则直接返回下标,nums[mid] < target 则target在右半区间, left 右移;nums[mid] > target 则target在左半区间,right 左移。

核心思想:不断排除不存在解的区间,直至最后剩下一个

学习大神经验:从一个元素什么时候不是解开始考虑下一轮搜索区间是什么。区间 [left, right] 里可能存在目标元素,我们要在循环体里排除一定不存在目标元素的区间,用排除条件来确定下一轮包含解的区间。如果是 [mid, right] 就对应 left = mid ,如果是 [left, mid - 1] 就对应 right = mid - 1。再根据下一轮区间的取法确定mid的计算式。

注意:

  • while(left < right) 退出循环的时候,有 left == right 成立,区间 [left, right] 只剩下1 个元素,这个元素有可能是我们要找的元素。可能要进行判断处理。
  • 区间划分与mid取法的关系:
    mid = left + (right - left) / 2,向下取整,mid在左区间,对应[left, mid] 与 [mid + 1, right] 。
    mid = left + (right - left + 1) / 2,向上取整,mid在右区间,对应 [left, mid - 1] 与 [mid, right] 。
    理解记忆:如果区间只有两个数,这样划分不会进入死循环。

分析此题知,如果nums中的数可能都小于target,需要单独处理。并且严格小于target的值一定不是解,从而得到下一轮区间。

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        if(nums.back() < target) return nums.size();

        int left = 0;
        int right = nums.size() - 1;

        while(left < right){
            int mid = left + (right - left) / 2; // 避免溢出

            if(nums[mid] < target){ // 排除一定不存在的元素,确定下一轮区间
                left = mid + 1; // [mid + 1, right]
            } else right = mid; // [left, mid]
        }
        return left;
    }
};

思考流程总结:

  1. 单独判断一定不在区间 [left,right] 里的情况
  2. 开始二分:判断区间里的元素什么时候不是解,从而确定下一轮搜索区间
  3. 判断mid的计算是否对应区间。
    mid = left + (right - left) / 2,对应[left, mid] 与 [mid + 1, right] ;
    mid = left + (right - left + 1) / 2,对应 [left, mid - 1] 与 [mid, right] 。

注:
循环的条件也可以为left <= right,此时为在循环体内部找目标元素,将情况分为三个分支进行讨论。当确定目标元素一定在数组中时,也可以使用这种写法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值