二分查找Java版本

时间:2024-04-22 07:03:18

二分查找

* 二分查找
* 特点,数组有序(升序)

基础版

public static int binarySearchBasic(int[] a, int target) {
    //定义边界
    int left = 0, right = a.length;

    //判断边界是否有值
    while (left < right) {
        int mid = (left+right) >>> 1;
        if (a[mid] > target) right = mid; //目标在左边
        else if (a[mid] < target) left = mid + 1; //目标在右边
        else return mid;
    }

    return -1;
}

平衡板

* 平衡二分查找
* 特点:左边和右边的执行次数一样
* 优点:减少循环内的平均次数
public static int binarySearchBasic2(int[] a, int target) {
    int left = 0,right = a.length;
    while (1<right-left){
        int mid = (right+left)>>>1;
        if (target <a[mid]){
            right = mid ;
        }else {
            left = mid;
        }
    }
    if (a[left]== target){
        return left;
    }else {
        return -1;
    }
}

LeftMost

/*
* 找到重复元素最左侧元素下标
* 找不到返回 -1
* */
public static int LeftMostBinarySearchBasic(int[] a, int target) {
    //定义边界
    int left = 0, right = a.length-1;
    //目标下标
    int index = -1;
    //判断边界是否有值
    while (left <= right) {
        int mid = (left+right) >>> 1;
        if (a[mid] > target) right = mid-1; //目标在左边
        else if (a[mid] < target) left = mid + 1; //目标在右边
        else { index = mid; //记录下标
               right = mid - 1; //左移下标,查找最左边的值
        }
    }
    return index;
}
/**
 *
 * @param a  待查找的升序数组
 * @param target  待查找的目标值
 * @return  返回>=target 最靠左的索引位置
 */
public static int LeftMostBinarySearchBasic2(int[] a, int target) {
    //定义边界
    int left = 0, right = a.length;
    //判断边界是否有值
    while (left < right) {
        int mid = (left+right) >>> 1;
        if (a[mid] >= target) right = mid -1; //目标在左边
        else if (a[mid] < target) left = mid + 1; //目标在右边
    }
    return left;
}

RightMost

/*
 * 找到重复元素最右侧元素下标
 * 找不到返回 -1
 * */
public static int RightMostBinarySearchBasic(int[] a, int target) {
    //定义边界
    int left = 0, right = a.length-1;
    //目标下标
    int index = -1;
    //判断边界是否有值
    while (left <= right) {
        int mid = (left+right) >>> 1;
        if (a[mid] > target) right = mid-1; //目标在左边
        else if (a[mid] < target) left = mid + 1; //目标在右边
        else {
            index = mid; //记录下标
            left = mid + 1; //右移下标,查找最右边的值
        }
    }
    return index;
}
/**
 * @param a      待查找的升序数组
 * @param target 待查找的目标值
 * @return 返回< =target 最靠右的索引位置
 */
public static int RightMostBinarySearchBasic2(int[] a, int target) {
    //定义边界
    int left = 0, right = a.length;
    //判断边界是否有值
    while (left < right) {
        int mid = (left + right) >>> 1;
        if (a[mid] > target) right = mid - 1; //目标在左边
        else left = mid + 1; //目标在右边
    }
    return right;
}

LeftRightMost应用

image-20240416224250826

名词解释

  • 前任:比目标值小的,更靠右的
  • 后任:比目标值大的,更靠左的
  • 最近邻居:前后任相比,更小的

leftmost — 求排名

求目标数排名

求排名: leftmost(4) = 2 +1
leftmost(5) = 5 +1

即 leftmost(*) + 1

leftmost — 求前任

求前任:leftmost(4) -1

​ leftmost(5) -1

rightmost — 后前任

求前任:rightmost(4)+1

​ rightmost(5) +1