leetCode-35: 搜索插入位置

题目描述:

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

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

示例1:

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

提示:

nums 为无重复元素的升序排列数组。

解题1:暴力解法:直接遍历数组,与 target 进行比较,需要注意的是,如果 target 比数组中的某个元素大,则继续循环,如果等于或者小于某个元素,则直接返回该元素的下标。同时还有一点,如果数组已经遍历完了,仍然没有找到 target 的准确位置,那么我们就认为 target 比数组中的每个元素都大,则直接返回数组大小即为 target 的下标。此方法时间复杂度为 O(n),空间复杂度为 O(1)。代码如下:

public static int searchInsert(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        if (target <= nums[i]) {
            return i;
        }
    }
    // 如果 target 大于所有元素,或者数组为空,直接返回数组大小
    return nums.length;
}

解题2:二分法:升序且无重复元素的题目要求正好适用于二分法,如果有重复数据的话二分法返回的数据还不一定是唯一的。时间复杂度是 O(logn),空间复杂度是 O(1)。需要注意的是,使用二分法的时候需要处理好边界值,即到底是 while(left < right) 还是 while(left <= right),到底是 right = middle 呢,还是 right = middle - 1?

当 target 位于 [left, right] 的左闭右闭区间时,代码如下:

public static int searchInsert2(int[] nums, int target) {
    int size = nums.length;
    int left = 0;
    // 定义 target 在左闭右闭的区间里,[left, right]
    int right = size - 1;
    // 当 left == right 时,区间 [left, right] 依然有效
    while (left <= right) {
        // 防止溢出,等同于(left + right) / 2
        int middle = left + ((right - left) / 2);
        if (nums[middle] > target) {
            // target 在左区间, 所以[left, middle - 1]
            right = middle - 1;
        } else if (nums[middle] < target) {
            // target 在右区间,所以[middle + 1, right]
            left = middle + 1;
        } else {
            // nums[middle] == target
            return middle;
        }
    }
    return right + 1;
}

当 target 位于 [left, right) 的左闭右开区间时,代码如下:

public static int searchInsert3(int[] nums, int target) {
    int size = nums.length;
    int left = 0;
    // 定义 target 在左闭右闭的区间里,[left, right)
    int right = size;
    // 当 left == right 时,在[left, right)区间无效
    while (left < right) {
        // 防止溢出,等同于(left + right) / 2,也等同于 left + ((right - left) / 2)
        int middle = left + ((right - left) >> 1);
        // target 在左区间,在[left, middle)中
        if (nums[middle] > target) {
            right = middle;
        } else if (nums[middle] < target) {
            // target 在右区间,在 [middle+1, right)中
            left = middle + 1;
        } else {
            // nums[middle] == target
            return middle;
        }
    }
    return right;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值