核心技能点-二分查找

二分是针对一个有序的数组中的查找,每次搜索都可以将搜索空间减半;效率可见一斑。

但是,写出一个不出bug,简洁,优雅的代码并不容易,接下来,我们来分析一下:

 

中间下标:mid

对于一个数组来说,比如:

[1, 4, 5, 6] 或 [1, 4, 5, 6, 7] 我们定义中位数有两种:

第一种为 下中位数:(length-1)/ 2;

第二种为 上中位数:length / 2;

我们分析一下,对于下中位数来说,当长度为奇数,比如5,mid 就会是 2;

                                                          当长度为偶数,比如4,mid 就会是 1;

总结就是一句话,下中为数在可以中分的情况下,取正中间;不可以中分的情况下取靠左的数。

上中位数在可以中分时也取正中间,不可以中分时取靠右。

你每次在循环取中位数的时候就用  mid = (left + right) / 2;

为了防止溢出,你要这样写: mid = left + (hight - left) / 2。

 

判断找到元素的返回终结条件

left > right  ( 即下一轮的搜索空间:无)

返回值可以直接为 left, 为什么?

left 在遇到比目标值小的mid 前进为 mid; 否则保持原位;如果在数组中找到了这个元素直接返回mid;

若没有找到,直接返回 left;

这个left就是该元素应该插入数组中的位置。

[1,  2] 找 3;

第一次取mid = 0;

target比1大;要更新 left

left = left+1 =  1;

target 比 2 大,又要更新left

left = left +1 比 right 大 ,故返回 left;为 2;即插入的位置是2;

Java 代码:

package temp0;

public class Solution {

    public static void main(String[] args){
        Solution solution = new Solution();
        int[] nums = {1,2,3};
        solution.searchInsert(nums, 2);
    }

    public int searchInsert(int[] nums, int target) {

        int left = 0;
        int right = nums.length-1;
        int mid = 0;

        while(left<=right){

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

            if (target>nums[mid]){
                left = mid+1;
            }
            if(target<nums[mid]){
                right = mid-1;
            }
            if(target==nums[mid]){
                System.out.println(mid);
                return mid;
            }
        }
        System.out.println(left);
        return left;

    }

}

第二种情况,有重复元素的?

[ 1, 2, 3, 4, 4, 4, 5 , 6,7] 查找 4;

为了找到第一个4,在mid<target时正常操作;

在mid>=target 时,说明应该向左查找;right 向左逼近;

同样等到 left 比 right还大的时候,说明 left 是最适合放4的位置,

Java 代码如下:

package temp0;

public class Solution {

    public static void main(String[] args){
        Solution solution = new Solution();
        int[] nums = {1};
        solution.searchInsert(nums, -1);
    }

    public int searchInsert(int[] nums, int target) {

        int left = 0;
        int right = nums.length-1;
        int mid = 0;

        while(left<=right){

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

            if (target>nums[mid]){
                left = mid+1;
            }
            else{
                right = mid-1;
            }
        }
        System.out.println(left);
        return left;

    }
}

这段代码对 :数组长度,元素是否重复,无要求。

但是注意这里的元素都是闭区间的。

核心技能:

    以上

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值