LeetCode35:搜索插入位置(数组-二分查找法)

这篇博客介绍了LeetCode35题的解决方案,重点是使用二分查找法来搜索目标值在排序数组中的插入位置。文章详细阐述了两种方法,包括暴力求解和二分查找法,其中二分查找法具有更高的时间效率,为O(logN)。

搜索插入位置

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

方法1:暴力求解
1、从数组的左边遍历到右边,如果遇到相等的元素,直接返回下标;
2、遇到第 1 个严格大于 target 的元素,返回这个元素的下标;
3、如果数组里所有的元素都严格小于 target,返回数组的长度 len。
时间复杂度O(N),空间复杂度O(1)。

     /**
     * 暴力求解:循环一遍数组如果遇到相同target的就返回下标,否则返回严格大于target的第一个元素
     * 时间复杂度:O(n)
     * @param nums
     * @param target
     * @return
     */
    public int searchInsert(int[] nums, int target) {

        for(int i = 0;i < nums.length;i++){

            if(nums[i] == target){
                return i;
            }else if(nums[i]>target){
                return i;
            }

        }
        return nums.length;
    }

方法2:二分查找
1、插入位置有可能在数组的末尾,需要单独判断,返回数组的长度;
2、插入的位置是等于或者大于 target 的第 1 个元素的位置;
3、所以:严格小于 target 的元素一定不是解,在循环体中将左右边界 left 和 right 逐渐向中间靠拢,最后 left 和 right 相遇,找到插入元素的位置。
时间复杂度:O(logN),空间复杂度O(1)。

 	/**
     * 搜索插入位置:有序数组,可以通过二分查找
     * @param nums
     * @param target
     * @return
     */
    public int searchInsert(int[] nums, int target) {

        if(nums.length <1){
            return 0;
        }

        //target比数组中最后一个数还大时,返回数组的长度
        if(nums[nums.length-1] <target){
            return nums.length;
        }

        int left =0;
        int right = nums.length - 1;
        while (left <= right){
            int middle = left + ( right-left)/2;

            //等于是返回下标
            if(target == nums[middle]){
                return middle;

                // 严格小于target的元素一定不是解
            }else if(target > nums[middle]){
                //下一次搜索区间:[middle+1,right]
                left = middle +1;
            }else{
                //target < nums[middle]
                //下一次搜索区间: [left, mid-1]
                right = middle -1;
            }
        }

        return left;
    }

二分查找模板:

      /**
     * 二分查找:对于有序数组(泛型):明确变量的含义以及循环不变量的维护
     * @return
     */
    public<E extends Comparable<E>> int binarySearch(E arr[],int n,E target){
        //在[l...r]的范围里寻找target(循环不变量:控制边界)
        int l=0 ,r =n-1;
        while(l<=r){
            //当l == r 时,区间[l...r]依然有效
            //整形溢出:用减法而不是加法:(r+l)/2
            int mid = l+(r-1)/2;
            //此时中间元素就是要寻找的target
            if(target.compareTo(arr[mid]) == 0){
                return mid;
            }
            //要寻找的元素target比中间元素要大
            if(target.compareTo(arr[mid]) >0){
                l = mid +1;
            }else{
                //要寻找的元素target比中间元素要小
                r = mid -1;
            }
        }
       return  -1;
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值