算法基础练习——二分法

1.基本二分查找

一个有序数组arr[],使用二分查找其中的num,返回Boolean值。

思路:三个索引变量,L、R、mid,其中mid=(L+R)/2,循环条件while(L<=R),if条件比较arr[mid]与num的关系,进而将mid(+1/-1)赋值给L或R值,逐步缩小查询范围,直至arr[mid]= =num。

具体代码如下:

public static boolean find(int[] arr, int num) {
    //边界条件
    if (arr == null || arr.length == 0) {
        return false;
    }
    //二分查询逻辑
    int L = 0;
    int R = arr.length - 1;
    int mid = 0;
    while (L <= R) {
        mid = (L + R) / 2;
        if (arr[mid] < num) {
            L = mid + 1;
        } else if (arr[mid] > num) {
            R = mid - 1;
        } else if (arr[mid] == num) {
            return true;
        }
    }
    return false;
}

2.二分查找扩展:

(1)查找某数最左位置

一个有序数组arr[],使用二分查找其中>=num最左的位置,返回索引值。

例:有序数组arr[0,1,2,2,3,4,5],其中>=2最左位置的索引为2。

思路:三个索引变量,L、R、mid,其中mid=(L+R)/2,一个记录索引值变量index,循环条件while(L<=R)。利用二分法更新查询范围,且只有当arr[mid]的值在>=num内范围,才更新索引值index=mid,使index逐渐逼近>=num最左的位置。

具体代码如下:

public static int findIndex(int [] arr,int num){
     //边界条件
    if (arr==null||arr.length==0){
        return -1;
    }
    //二分查询逻辑
    int L=0;
    int R= arr.length-1;
    int mid=0;
    int index=-1;
    while (L<=R){
        mid=(L+R)/2;
        if (arr[mid]>=num){
            R=mid-1;
            index=mid;
        }else if (arr[mid]<num){
            L=mid+1;
        }
    }
    return index;
}

(2)数组局部最小

局部最小定义:当arr[0]<arr[1],arr[0]为局部最小;当arr[n-1]>arr[n]时(n=arr.length-1),arr[n]为局部最小;当arr[i-1]>arr[i]<arr[i+],arr[i]为局部最小。

需求:查找一个数组的局部最小,并返回;该数组无序,且相邻两数不可相等。

思路:先寻找前两种定义是否满足,若前两种定义不满足,则根据第三种定义查找局部最小。第三种定义查找局部最小时,取中间mid索引值,并进行循环条件判断,当mid-1>mid<mid+1时,即满足定义返回局部最小;若mid>mid-1,则在mid-1与0间必然存在局部最小,利用二分法缩小范围;若mid>mid+1则在mid+1与n之间必有最小值,利用二分法缩小范围。

mid-1与0间或mid+1与n之间必然存在局部最小的原理图如下:

 即根据局部最小定义,最小值必然存在于递减方向。

具体代码如下:

public static int findMin(int[] arr) {
    //最大索引号
    int n = arr.length - 1;
    //定义起始二分左右索引
    int L = 0;
    int R = n;
    //边界条件
    if (arr.length == 1 || arr == null) {
        return -1;
    }
    //定义1判断
    if (arr[0] < arr[1]) {
        return arr[0];
    }
    //定义2判断
    if (arr[n] < arr[n - 1]) {
        return arr[n];
    }
    //定义1、2都不满足,二分法循环条件判断
    int mid = 0;
    while (L < R) {
        //二分中间索引
        mid = (L + R) / 2;
        //条件判断
        if (arr[mid - 1] > arr[mid] && arr[mid] < arr[mid + 1]) {
            return arr[mid];
        } else if (arr[mid - 1] < arr[mid]) {
            R = mid - 1;
        } else if (arr[mid+1] < arr[mid]) {
            L=mid+1;
        }

    }
    return -1;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值