4种二分查找模版讲解

视频讲解链接:【二分查找模版】四种变形的二分查找

实现代码看这里

package sort;

public class BanarySort {

    public static void main(String[] args) {
        int[] arr = new int[]{1, 2,3,3,3,4,5,5,7};
        int target = 3;
        int index = floor_lower(arr, target);
        System.out.println("index = "+ index + ", value = " + arr[index]);

    }

    //1.寻找第一个大于 target 的元素的下标,案例:arr[1, 2,3,3,3,4,5,5,7], target = 3。
    public static int upper(int[] arr, int target){
    // 二分查找需要想清楚的点
        int l = 0;
        int r = arr.length - 1;
        // 判断特殊情况
        if(arr[r] <= target){
            return -1;
        }
        //[l,r],,在我们二分查找的过程中,不断缩小我们的查找范围,直到范围里面只有一个元素,那个就是我们要找的元素了
        while(l < r){
            int mid = (r - l) / 2 + l;
            if(arr[mid] > target){
                //[l ,mid, r]
                r = mid;
            } else if(arr[mid] == target){
                l = mid + 1;
            }else {//arr[mid] < target
                l = mid + 1;
            }
        }
        return l;
    }

    //2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,
    // 如果不存在,则返回第一个大于 target 的元素下标
    //案例:arr[1, 2,3,3,3,4,5,5,7], target = 3。
    public static int floor_upper(int[] arr, int target){
        int l = 0;
        int r = arr.length - 1;
        // 判断特殊情况
        if(arr[r] < target){
            return -1;
        }
        //[l,r],,在我们二分查找的过程中,不断缩小我们的查找范围,直到范围里面只有一个元素,那个就是我们要找的元素了
        while(l < r){
            int mid = (r - l) / 2 + l;
            if(arr[mid] > target){
                //[l ,mid, r]
                r = mid;
            } else if(arr[mid] == target){
                l = mid + 1;
            }else {//arr[mid] < target
                l = mid + 1;
            }
        }

        if(l - 1 >= 0 && arr[l - 1] == target){
            return l -1;
        }

        return l;
    }

    //3.寻找最后一个小于 target 的元素的下标
    // [1, 2,3,3,3,4,5,5,7],target = 3;
    public  static int lower(int[] arr, int target){
        int l = 0;
        int r = arr.length - 1;
        // 判断特殊情况
        if(arr[l] >= target){
            return -1;
        }
        //[l,r],,在我们二分查找的过程中,不断缩小我们的查找范围,直到范围里面只有一个元素,那个就是我们要找的元素了
        while(l < r){
            // r = 1,l = 0,mid = 0
            int mid = (r - l + 1) / 2 + l;
            if(arr[mid] > target){
                //[l ,mid, r]
                r = mid - 1;
            } else if(arr[mid] == target){
                r = mid - 1;
            }else {//arr[mid] < target
                l = mid;
            }
        }
        //
        return l;
    }

    // 4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,
    // 如果不存在,则返回最后一个小于 target 的元素的下标
    //[1, 2,3,3,3,4,5,5,7],target = 3;
    public static int floor_lower(int[] arr, int target){
        int l = 0;
        int r = arr.length - 1;
        // 判断特殊情况
        if(arr[l] > target){
            return -1;
        }
        //[l,r],,在我们二分查找的过程中,不断缩小我们的查找范围,直到范围里面只有一个元素,那个就是我们要找的元素了
        while(l < r){
            // r = 1,l = 0,mid = 0
            int mid = (r - l + 1) / 2 + l;
            if(arr[mid] > target){
                //[l ,mid, r]
                r = mid - 1;
            } else if(arr[mid] == target){
                r = mid - 1;
            }else {//arr[mid] < target
                l = mid;
            }
        }
        //
        if(l + 1 < arr.length && arr[l + 1] == target){
            return l + 1;
        }
        return l;
    }
}


发表评论

后才能评论

评论(1)

  • 20清晨 永久会员 2025-05-03 11:49 下午

    int upper(vector<int>& arr, int target)
    {
    int l = 0;
    int r = arr.size() - 1;

    if (arr[r] <= target)
    {
    return -1;
    }

    int res = 0;

    while (l <= r)
    {
    int mid = l + (r - l) / 2;
    if (arr[mid] > target)
    {
    r = mid - 1;
    res = mid;
    }
    else
    {
    l = mid + 1;
    }
    }
    return res;
    }

    //如果元素存在target,返回最后一个等于target的元素下标,否则返回第一个大于target的元素下标
    int floor_upper(vector<int>& arr, int target)
    {
    int l = 0;
    int r = arr.size() - 1;
    if (arr[r] < target)
    {
    return -1;
    }

    int res = -1;
    while (l <= r)
    {
    int mid = l + (r - l) / 2;
    if (arr[mid] > target)
    {
    res = mid;
    r = mid - 1;
    }
    else if (arr[mid] == target)
    {
    //找到target时,收缩左边界找最后一个
    res = mid;
    l = mid + 1;
    }
    else
    {
    l = mid + 1;
    }
    }
    //检查res位置是否为target
    if (res < arr.size() && arr[res] == target)
    {
    while (res + 1 < arr.size() && arr[res + 1] == target)
    {
    res++;
    }
    return res;
    }
    return res;
    }

    //寻找最后一个小于target的下标
    int lower(vector<int>& arr, int target)
    {
    int l = 0;
    int r = arr.size() - 1;
    int res = -1;

    while (l <= r)
    {
    int mid = l + (r-l)/2;
    if (arr[mid] < target)
    {
    res = mid;
    l = mid + 1;
    }
    else
    {
    r = mid - 1;
    }
    }
    return res;
    }

    //返回第一个等于target的下标
    int floor_lower(vector<int>& arr, int target)
    {
    int l = 0;
    int r = arr.size() - 1;
    int res = -1;

    while (l <= r)
    {
    int mid = l + (r - l) / 2;
    if (arr[mid] >= target)
    {
    if (arr[mid] == target)
    {
    res = mid;
    }
    r = mid - 1;//继续向左寻找更小的
    }
    else
    {
    res = mid;//记录最后一个小于target的位置
    l = mid + 1;
    }
    }
    if (res != -1 && arr[res] == target)
    {
    while (res > 0 && arr[res - 1] == target)
    {
    res--;
    }
    return res;
    }
    return res;
    }