Note-二分法

本文详细解析了二分查找算法的原理与实现,通过实例分析了不同边界情况下的运行过程,包括目标值存在于数组内但不匹配的情况以及目标值不在数组范围内的情况。针对寻找数组中特定值的最左或最右下标,提出了相应的优化算法。最后,鼓励读者通过解决LeetCode题目来进一步实践二分查找技巧。

二分法

在网上搜,能看见比较详细的二分法的介绍,但是笔者还是想去梳理一下,因为想要真正理解二分法的代码和二分法的原理是不一样的。首先,看一个比较常用的二分法算法。

    public int binarySearch(int nums[],int target){
        Arrays.sort(nums);
        int left=0,right=nums.length-1;
        while(left<=right){
            int mid=(left+right)/2;
            if(nums[mid]==target){
                return mid;
            }
            else if(nums[mid]>target){
                right=mid-1;
            }
            else {
                left=mid+1;
            }
        }
        return left;
    }

我们主要从两个边界问题来考虑这个函数会怎么样:

  • 如果nums的取值范围在[a,b],并且target值属于[a,b],但是target不等于nums中的任意元素。对于这种情况下,我们能够得到binarySearch返回一个index值,但是nums[index]并不对于target。

    如nums=[0,1,2,3,4,5,6,7,8] target=2.5

    轮次leftrightmid
    1084
    2031
    3232
    4333
    5322

    最终输出的值为3,因为找不到target。

  • 如果nums的取值范围在[a,b],并且target值不属于[a,b],则会出现超过数组的index

    如nums=[0,1,2,3,4,5,6,7,8] target=9

    轮次leftrightmid
    1084
    2586
    3787
    4888
    5988

    最终输出的值是9,找不到index。

    这个方法我们再找最终输出的index是否满足要求,需要判断index是否在nums数组范围的同时判断nums[index]是否对于target,这样子就比较麻烦,所以需要改进一下算法

    public int binarySearch(int nums[],int target){
        Arrays.sort(nums);
        int left=0,right=nums.length-1;
        while(left<right){
            int mid=(left+right)/2;
            if(nums[mid]==target){
                return mid;
            }
            else if(nums[mid]>target){
                right=mid;
            }
            else {
                left=mid+1;
            }
        }
        return left;
    }

该方法就不会越界,但是还是需要判断nums[index]是否等于target。

  • 那么对于nums=[0,1,2,3,4,4,4,5,6,7],target=4,并且我想得到最左边的4的下标,我们怎么改进算法呢?

        public int binarySearch(int nums[],int target){
            Arrays.sort(nums);
            int left=0,right=nums.length-1;
            while(left<right){
                int mid=(left+right)/2;
    			if(nums[mid]>=target){
                    right=mid;
                }
                else {
                    left=mid+1;
                }
            }
            return left;
        }
    
  • 同理,我们想找到最右边的4的下表,我们应该怎么改进呢?

    可以思考一下,然后见下面的答案:

       public int binarySearch(int nums[],int target){
            Arrays.sort(nums);
            int left=0,right=nums.length-1;
            while(left<right){
                int mid=(left+right)/2+(left+right)%2;
                if(nums[mid]<=target){
                    left=mid;
                }
                else {
                    right=mid-1;
                }
            }
            return right;
        }
    

    注意这个mid是如何取值的,本质上也是相对于去最左边值的对偶关系

  • 那么介绍完了二分法了之后,可以尝试做一下leetcode题目

    https://leetcode-cn.com/problems/minimum-time-to-complete-trips/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值