二分法(折半查找法)查找第一个大于等于给定值的元素

在arr数组上,找满足>=value的最左位置

在这里插入图片描述

带有对数器的二分查找

1、查找第一个大于等于给定值的元素

public class Code05_BSNearLeft {

    //在arr上,找满足>=value的最左位置    O(logn)
    public static int nearestIndex(int[] arr,int value){
        int L=0;
        int R=arr.length-1;
        int index = -1;//记录最左边的对号
        while(L<=R){
            int mid=L+((R-L)>>1);
            //发现右侧有大于目标值的,抛弃右边,右边下标R=mid-1
            if(arr[mid]>=value){
                index=mid;
                R=mid-1;
            }else {
                L=mid+1;
            }
        }
        return index;
    }

    //用来作对比测试的  暴力循环对比方法   O(n)
    public static int test(int[] arr,int value){
        for(int i=0;i<arr.length;i++){
            if(arr[i]>=value){
                return i;
            }
        }
        return -1;
    }

    //生成一个随机数数组
    public static int[] generateRandomArray(int maxSize,int maxValue){
        //Math.random()   [0,1]随机数
        //N*Math.random()  [0,N]随机数
        int [] arr=new int[(int) ((maxSize+1)*Math.random())];
        for(int i=0;i<arr.length;i++){
            //为了得到[-N,N] 有负数
            arr[i]= (int) ((maxSize+1)*Math.random())-(int) (maxValue*Math.random());
        }
        return arr;
    }

    //打印出数组
    public static void printArray(int[] arr){
        if (arr==null){
            return;
        }
        for (int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
        System.out.println();
    }

    //主方法进行测试
    public static void main(String[] args) {
        int testTime=500000;
        int maxSize=100;
        int maxValue=100;
        boolean succeed=true; //完成与否标记
        for(int i=0;i<testTime;i++){
            //1 生成自定义大小的随机数组
            int [] arr=generateRandomArray(maxSize,maxValue);
            //2 利用系统的Sort方法排序成标准的有序数组
            Arrays.sort(arr);
            //3 生成一个随机数,进行测试
            int value=(int)((maxSize+1)*Math.random())-(int)(maxValue*Math.random());
            if (test(arr,value)!=nearestIndex(arr,value)){
                printArray(arr);
                System.out.println("目标值: "+value);
                System.out.println("暴力完的下标: "+test(arr,value));
                System.out.println("二分法的下标: "+nearestIndex(arr,value));
                succeed=false;
                break;
            }
        }
        System.out.println(succeed?"Nice!漂亮!":"Fucking fucked!继续努力!");
    }
}

2、查找最后一个小于等于给定值的元素

public class Code06_BSNearRight {

    //在arr上,找满足<=value的最右位置    O(logn)
    public static int nearestIndex(int[] arr,int value){
        int L=0;
        int R=arr.length-1;
        int index = -1;//记录最左边的对号
        while(L<=R){
            int mid=L+((R-L)>>1);
            //发现左侧有小于目标值的,抛弃左边,左边下标L=mid+1
            if(arr[mid]<=value){
                index=mid;
                L=mid+1;
            }else {
                R=mid-1;
            }
        }
        return index;
    }

    //用来作对比测试的  暴力循环对比方法   O(n)
    public static int test(int[] arr,int value){
        //倒序循环,找出最右边的那个值
        for(int i=arr.length-1;i>=0;i--){
            if(arr[i]<=value){
                return i;
            }
        }
        return -1;
    }

    //生成一个随机数数组
    public static int[] generateRandomArray(int maxSize,int maxValue){
        //Math.random()   [0,1]随机数
        //N*Math.random()  [0,N]随机数
        int [] arr=new int[(int) ((maxSize+1)*Math.random())];
        for(int i=0;i<arr.length;i++){
            //为了得到[-N,N] 有负数
            arr[i]= (int) ((maxSize+1)*Math.random())-(int) (maxValue*Math.random());
        }
        return arr;
    }

    //打印出数组
    public static void printArray(int[] arr){
        if (arr==null){
            return;
        }
        for (int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
        System.out.println();
    }

    //主方法进行测试
    public static void main(String[] args) {
        int testTime=500000;
        int maxSize=100;
        int maxValue=100;
        boolean succeed=true; //完成与否标记
        for(int i=0;i<testTime;i++){
            //1 生成自定义大小的随机数组
            int [] arr=generateRandomArray(maxSize,maxValue);
            //2 利用系统的Sort方法排序成标准的有序数组
            Arrays.sort(arr);
            //3 生成一个随机数,进行测试
            int value=(int)((maxSize+1)*Math.random())-(int)(maxValue*Math.random());
            if (test(arr,value)!=nearestIndex(arr,value)){
                printArray(arr);
                System.out.println("目标值: "+value);
                System.out.println("暴力完的下标: "+test(arr,value));
                System.out.println("二分法的下标: "+nearestIndex(arr,value));
                succeed=false;
                break;
            }
        }
        System.out.println(succeed?"Nice!漂亮!":"Fucking fucked!继续努力!");
    }
}
  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值