二分查找-java版

二分查找

在网上具体学习了二分查找的一些基本情况, 现在分享一下, 有问题欢迎评论(没有经过大量测试)

基础版

package basicAlgorithm;

public class binarySearch {
    public static void main(String[] args) {
        int[] a = {2, 3, 4, 5, 7, 8, 9};
        // 测试代码
        System.out.println(BinarySearch(a, 2));
    }
    // 定义二分查找函数
    public static int BinarySearch(int a[], int target) {
        int beign = 0, end = a.length - 1;
        while (beign <= end) {
            int mid = (beign + end) >> 1;
            if (a[mid] > target) {
                end = mid - 1;
            } else if (a[mid] < target) {
                beign = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
}

注意 使用移位计算

取mid = (begin + end) >> 1 而不是直接除以2, 直接除以2可能会超过最大整型导致出现负数

改动版(边界情况改动)

public static int BinarySearch2(int[] a, int target) {
        int beign = 0, end = a.length;
        while (beign < end) {
            int mid = (beign + end) >> 1;
            if (a[mid] > target) {
                end = mid;
            } else if (a[mid] < target) {
                beign = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }

时间复杂度 O ( l o g n ) O(logn) O(logn)

空间复杂度 O ( 1 ) O(1) O(1) 用了常数个指针

上述缺点: 查找元素为最小元素, 内部循环 n n n次需要做if判断 n n n次, 但如果是最大元素, 需要做if判断 2 n 2n 2n次, 不平衡

平衡版二分

public static int BinarySearch3(int[] a, int target) {
    int begin = 0, end = a.length;
    while((end-begin)>1){
        int m = (end + begin) >> 1;
        if(target < a[m])
            end = m;
        else begin = m;
    }
    if(a[begin]==target)
        return begin;
    else return -1;
}

上述缺点及每次都要比较最多次数

java中的二分查找函数用的是**基础版**, 返回的是该值应该插入位置的负数值-1

实现在对应位置插入目标值

// 如果查询到的目标值不存在, 插入到对应位置, 并返回数组
public static int[] insertBinarySearch(int[] a, int target) {
    int insertIndex = Arrays.binarySearch(a, target);
    if (insertIndex > 0)
        return a;
    insertIndex = Math.abs(insertIndex) - 1;
    // 拷贝后的数组
    int[] newArray = new int[a.length + 1];
    System.arraycopy(a, 0, newArray, 0, insertIndex);
    newArray[insertIndex] = target;
    System.arraycopy(a, insertIndex, newArray, insertIndex + 1, a.length - insertIndex);
    return newArray;
}

特殊情况下找最左和最右的目标值(即有重复目标值的情况)

// 找到最左的目标值(如果有重复的)
public static int BinarySearchLeft(int[] a, int target) {
    int begin = 0, end = a.length - 1;
    int ans = -1;
    while (begin <= end) {
        int mid = (begin + end) >> 1;
        if (a[mid] < target) {
            begin = mid + 1;
        } else if (a[mid] > target)
            end = mid - 1;
        else {
            ans = mid;
            end = mid - 1;
        }
    }
    return ans;
}
// 找到最右的目标值(如果有重复的)
public static int BinarySearchRight(int[] a, int target) {
    int begin = 0, end = a.length - 1;
    int ans = -1 // 标记为位;
    while (begin <= end) {
        int mid = (begin + end) >> 1;
        if (a[mid] < target) {
            begin = mid + 1;
        } else if (a[mid] > target)
            end = mid - 1;
        else {
            ans = mid;
            begin = mid + 1;
        }
    }
    return ans;
}

用二分找到小于等于目标的最大索引和大于等于目标的最小索引

// 用二分找到小于等于目标的最大索引
public static int BinarySearchRightMost(int[] a, int target) {
    int begin = 0, end = a.length - 1;
    while (begin <= end) {
        int mid = (begin + end) >> 1;
        if (a[mid] <= target) {
            begin = mid + 1;
        } else {
            end = mid - 1;
        }
    }
    return begin-1;
}

// 用二分找到大于等于目标的最小索引
public static int BinarySearchLeftMost(int[] a, int target) {
    int begin = 0, end = a.length - 1;
    while (begin <= end) {
        int mid = (begin + end) >> 1;
        if (a[mid] < target) {
            begin = mid + 1;
        } else if (a[mid] > target)
            end = mid - 1;
    }
    return begin;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值