算法通关村第九关——二分查找青铜挑战笔记

该部分主要针对二分查找这一高频考点进行总结,熟练掌握二分查找使用的前提条件,形成条件反射,理解掌握二分查找的递归模板非递归模板,从浅入深理解二分查找边界条件,并能够准确分析变式题目的边界条件!

什么时候可以考虑二分查找?答:元素有序!这很重要,有了这个前提条件,才能考虑二分查找!

1.二分查找模板——非递归

    public static int myBinarySearch1(int[] array, int low, int high, int target){
        while(low<=high){
            int mid = low + ((high - low) >> 1);
            if(array[mid] == target){
                return mid;
            } else if (array[mid] > target) {
                high = mid - 1;
            } else{
                low = mid + 1;
            }
        }
        return -1;
    }

2.二分查找模板-非递归

    public static int myBinarySearch2(int[] array, int low, int high, int target) {
        if(low <= high){
            int mid = low+ ((high - low) >> 1);
            if(array[mid] == target){
                return mid;
            } else if(array[mid] < target){
                return myBinarySearch2(array, mid+1, high, target);
            } else{
                return myBinarySearch2(array, low, mid + 1, target);
            }
        }
        return -1;
    }

3.二分查找变式问题

如果数组中元素有序,且存在重复元素,想获取重复元素的最左(右)侧,该如何应用二分查找模板呢?

别急,听我分析:

首先,我们需要使用二分查找模板找到待查的元素!只不过,找到元素后,需要找寻和这个元素相等的最左侧元素。该怎么找最左侧元素?答:顺序查找最左侧元素即可!

厘清思路,直接上代码!

    public static int mySearch1(int[] nums, int target) {
        if(nums == null || nums.length == 0) return -1;
        int low = 0;
        int high = nums.length - 1;
        while(low <= high){
            int mid = low +((high -low) >> 1);
            if(nums[mid] < target){
                low = mid + 1;
            } else if (nums[mid] > target) {
                high = mid -1;
            } else {
                //找最左侧的元素
                while(mid != 0 && nums[mid] == target) mid--;
                //最左侧元素下标为0时
                if(mid == 0 && nums[mid] == target) return mid;
                return mid + 1;
            }
        }
        return -1;
    }

上面的非递归二分查找思路我已经明白了,那么二分查找的递归模板该怎么进行呢,问题的关键点是,怎么二分查找最左侧的目标值呢?实际上在找到目标值后,将该目标值设为high,然后从左侧区域继续二分查找即可!厘清思路直接上代码!(体会二分查找的边界条件!)

    public static int search2(int[] nums, int target) {
        if (nums == null || nums.length == 0)
            return -1;
        return myBinSearch2(nums, target, 0, nums.length - 1);
    }
    
    private static int myBinSearch2(int[] nums, int target, int left, int right) {
        if(left > right) return -1;
        int mid = left + ((right - left)) >> 1;
        if(nums[left] == target) return left;
        if(nums[mid] > target) {
            return myBinSearch2(nums, target, left, mid -1);
        }else if(nums[mid] < target) {
            return myBinSearch2(nums, target, mid + 1, right);
        }else{ //相等,查找最左侧的
            return myBinSearch2(nums, target, left, mid);
        }
    }

OK,《算法通关村第九关——二分查找青铜挑战笔记》结束,喜欢的朋友三联加关注!关注鱼市带给你不一样的算法小感悟!(幻听)

再次,感谢鱼骨头教官的学习路线!鱼皮的宣传!小y的陪伴!ok,拜拜,第九关第二幕见!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值