35.搜索插入位置

12 篇文章 0 订阅
5 篇文章 0 订阅
本文探讨了如何利用二分查找算法在已排序的整数数组中高效定位目标值并确定其插入位置。通过三种实现方式对比,展示了从简单遍历到二分搜索的时间复杂度提升。关键点包括闭区间和开区间的二分法应用,以及针对四种可能情况的处理策略。
摘要由CSDN通过智能技术生成

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5
输出: 2
示例 2:
输入: [1,3,5,6], 2
输出: 1
示例 3:
输入: [1,3,5,6], 7
输出: 4

思路1

数组的遍历&比大小?
本来想用for(num:nums)。但是这样就不知道怎么拿到数组的下标。
所以还是乖乖for(int i=0; i<position; i++)。
因为输入的数组是升序的。
再考虑到要插入的数如果是最大的,就直接放在数组最后面,这时候直接返回数组长度就好了。
所以初始化position的时候直接让他等于数组的长度。
然后在for循环里去找。
只要找到了目标位置就可以重新给position赋值,跳出循环。

代码1- 时间复杂度 O(n)

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

解题思路2

昨天704.二分查找 的闭区间解法
参考Carl

代码2 O(log2n)

class Solution {
    public int searchInsert(int[] nums, int target) {
        //满足数组有序且不重复,使用二分法
        int len = nums.length;
        int left=0;
        int right=len-1;    //闭区间
        while(left <= right){   //闭区间。==有意义
            int mid = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] < target){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }
        // 分别处理如下四种情况
        // 目标值在数组所有元素之前  [0, -1]
        // 目标值等于数组中某一个元素  return middle;
        // 目标值插入数组中的位置 [left, right],return  right + 1
        // 目标值在数组所有元素之后的情况 [left, right], return right + 1
        return right + 1 ;
    }
}

解题思路3

二分法右侧开区间

代码3

class Solution {
    public int searchInsert(int[] nums, int target) {
        //满足数组有序且不重复,使用二分法
        int len = nums.length;
        int left=0;
        int right=len;    //右侧开区间
        while(left < right){   //右侧开区间。 等于号==没有意义
            int mid = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] < target){
                left = mid + 1;
            }else{
                right = mid;
            }
        }
               // 分别处理如下四种情况
        // 目标值在数组所有元素之前 [0,0)
        // 目标值等于数组中某一个元素 return middle
        // 目标值插入数组中的位置 [left, right) ,return right 即可
        // 目标值在数组所有元素之后的情况 [left, right),return right 即可
        return right;
    }
}

总结:二分法适用于有序存储。左右指针的区间定义,决定了左右区间的开和闭。如左右指针有意义,为闭区间,如指针无意义,为开区间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

asjodnobfy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值