Java算法 每日一题(一) 编号35:搜索插入位置

本系列为每日算法,主要借助@代码随想录与LeetCode网站的解析,仅做记录与鞭策使用。

编号35:搜索插入位置

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

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

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

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

输入: nums = [1,3,5,6], target = 7
输出: 4

提示:

1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 为 无重复元素 的 升序 排列数组
-104 <= target <= 104

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/search-insert-position

解析:

二分查找是非常经典的查找法,适用于有序的数组等结构,时间复杂度:O(logn),空间复杂度:O(1)。

既然本题已经提示,时间复杂度要为O(logn),显然是为了提示我们使用二分查找

二分查找的关键在于二分的边界界定,接下来写一个典型的二分查找示例。

可以看到,中位数的计算并没有用左右相加取半的方式,而是先取差值,再和左边界求和,这样做是为了避免超过int类型的大小,造成数据溢出。

public static int searchInsert(int sum, int[] nums) {
    //左侧区间,取得有效的左侧极限
    int left = 0;
    //右侧区间,取得有效的右侧极限
    int right = nums.length - 1;
    //因为上文的取值,代表这是一个闭区间,[left, right],所以可以相等
    while (left <= right) {
        //获取中位数使用位运算避免出现大于int极限的取值
        int index = left + ((right - left) >> 1);
        //当目标数比中位大,需要将左侧极限向中间移动
        if (sum > nums[index]) {
            //左侧极限获得到中位数的后一个数,因为中位数已经无效
            left = index + 1;
        //当目标数比中位小,需要将右侧极限向中间移动
        } else if (sum < nums[index]) {
            //右侧极限获得到中位数的前一个数,因为中位数已经无效
            right = index - 1;
        } else {
            //相等代表找到了需要的数
            return index;
        }
    }
    //如果未找到,代表整个循环已经结束,此时左右必然不再相等,但是此前最后一次必然是相等的
    //交汇时,因为取半累加的原因,导致最后一次必然是right-1,所以需要right+1或left的数值
    return right + 1;
}

你可能感兴趣的:(算法,笔记,LeetCode,算法,排序算法,leetcode)