Java练习题之搜索某个元素在数组中插入的位置

题目描述

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

题解示例

  • 示例 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

初次解题

class Solution {
    public int searchInsert(int[] nums, int target) {
        // 初始化索引 i 为 0
        int i = 0;
        // 如果数组长度为 1
        if (nums.length == 1) {
            // 如果数组中唯一的元素小于目标值,返回 1,表示目标值应插入在这个元素之后
            if (nums[0] < target) {
                return 1;
            } else {
                // 如果数组中唯一的元素大于等于目标值,返回 0,表示目标值应插入在这个元素之前(即数组开头)
                return 0;
            }
        }
        // 当 i 小于数组长度减 1 时循环
        while (i < nums.length - 1) {
            // 如果当前元素小于目标值
            if (nums[i] < target) {
                // 如果下一个元素大于等于目标值,返回 i + 1,表示目标值应插入在当前元素之后
                if (nums[i + 1] >= target) {
                    return i + 1;
                } else {
                    // 如果下一个元素也小于目标值,继续向后查找,i 自增
                    i++;
                }
            } else {
                // 如果当前元素大于等于目标值,返回 0,表示目标值应插入在当前元素之前(即数组开头)
                return 0;
            }
        }
        // 如果循环结束还没找到合适位置,说明目标值大于数组中所有元素,返回数组长度,表示目标值应插入在数组末尾
        return nums.length;
    }
}

复杂度分析

时间复杂度:在最坏的情况下,需要遍历整个数组,直到 i 达到 nums.length - 1。如果数组长度为 n,那么时间复杂度为O(n) 。

改进的做法 

class Solution {
    public int searchInsert(int[] nums, int target) {
        // 定义左边界指针和右边界指针
        int left = 0;
        int right = nums.length - 1;
        // 当左边界不超过右边界时进行循环查找
        while (left <= right) {
            // 计算中间位置
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                // 找到目标值,返回其索引
                return mid;
            } else if (nums[mid] < target) {
                // 目标值在中间值右侧,更新左边界
                left = mid + 1;
            } else {
                // 目标值在中间值左侧,更新右边界
                right = mid - 1;
            }
        }
        // 未找到目标值,返回左边界,即目标值应插入的位置
        return left;
    }
}

注意在数组中间下标的计算推荐使用

int mid = left + (right - left) / 2;

而不是,后者在一些情况下可能导致查找不准确或陷入死循环,会产生程序超时的情况发生

int mid = right / 2;

改进的好处 

采用的是二分查找法,每次循环都将搜索范围缩小一半,所以时间复杂度为O(log(n)) ,其中 n 是数组 nums 的长度。

二分查找法回顾

二分查找法:用于在有序数组中查找特定元素。(如果无序要先排序)

二分查找步骤

  1. 首先,确定一个查找区间,初始时,区间的左边界为数组的第一个元素索引,右边界为数组的最后一个元素索引。
  2. 然后,计算区间的中间位置,可以通过公式mid = left + (right - left) / 2来计算,这样可以避免整数溢出。
  3. 接着,将中间位置的元素与目标元素进行比较:  如果中间元素等于目标元素,查找成功,返回中间元素的索引。 如果中间元素大于目标元素,说明目标元素在中间元素的左侧,此时将右边界更新为mid - 1,缩小查找区间继续查找。 如果中间元素小于目标元素,说明目标元素在中间元素的右侧,此时将左边界更新为mid + 1,缩小查找区间继续查找。
  4. 重复上述步骤,直到找到目标元素或者左边界超过右边界(表示目标元素不在数组中)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值