LeetCode 第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

我的解法

思路

暴力搜索,从数组第一个值开始与目标值进行比较,如果目标值小于等于当前值则返回当前索引,否则比较下一个值;若数组遍历结束后仍未找到符合条件的值,则返回当前索引值+1

对应Java代码

class Solution {
    public int searchInsert(int[] nums, int target) {
        int i = 0;
        for (; i < nums.length; i++) {
            if (target <= nums[i]){
                return i;
            }
        }
        return i;
    }
}

复杂度分析

时间复杂度:O(N) 这里的N对应的是数组长度
空间复杂度:O(1) 用到常数个临时变量

更优的解法

思路

学习于公众号代码随想录,大佬讲的很清楚

二分法

  1. 适用场景
    (1)有序数组:二分查找的基础条件
    (2)无重复元素:一旦有重复元素,使用二分查找法返回的元素下表可能不是唯一的

  2. 难点——边界条件
    二分法的算法逻辑很容易理解,实际应用时的问题在于边界条件处理不好,例如到底是while (left < right)还是while (left <= right) ,是right = middle 呢,还是要right = middle - 1 呢?

    这里弄不清楚主要是因为「对区间的定义没有想清楚,这就是不变量」。要在二 分查找的过程中,保持不变量,这也就是「循环不变量」 (感兴趣的同学可以查一查)。
    【个人理解】循环不变量是指判断条件的定义不变,即下面自己定义的左闭右闭,左闭右不闭不变,根据这一点就可以选择循环中涉及到的各种边界值了。

对应Java代码

以这道题目来举例,以下的代码中定义 target 是在一个在左闭右闭的区间里,「也就是[left, right] (这个很重要)」。这就决定了这个二分法的代码如何去写,大家看如下代码:「大家要仔细看注释,思考为什么要写while(left <= right), 为什么要写right = middle - 1」。

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;
        int left = 0;
        int right = n - 1; // 定义target在左闭右闭的区间里, [left, rigth]
        while (left <= right) { // 当left==right, 区间[left,right]依然有效
            int middle = left + ((right - left) / 2); // 防止溢出 等同于(left + right)/2
            if (nums[middle] > target) {
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } else {
                return middle;
            }
        }
        // 分别处理如下四种情况
        // 目标值在数组所有元素之前  [0, -1]
        // 目标值等于数组中某一个元素  return middle;
        // 目标值插入数组中的位置 [left, right],return  right + 1
        // 目标值在数组所有元素之后的情况 [left, right], return right + 1
        return right + 1;
    }
}

复杂度分析

时间复杂度:O(logN)
空间复杂度:O(1)

收获总结

在数组搜索方面学习到了除暴力搜索外的另一种方法——二分法
并且了解了二分法适用的场景,掌握了实际应用时主要该注意的边界值处理方法,即认为设定一个边界原则(如左闭右闭),然后在另循环中的所有边界值都符合该规则,至于返回值(right+1),不确定的情况可以举个简单的例子看一下

以上的方法并不是什么定律,但是可以解决此类问题,可以理解成某一种类型题的解法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值