【二分查找专题】给出四种二分查找的模版

本问题对应课程链接:剑指offer刷题第四期

本次打卡的任务很简单,就是给出四种变形二分查找的模版代码,并且给出了对应的方法名字。

比如对于一个有序数组

arr = [1,2,3,3,3,4,5,5,7],target = 3,那么

1.寻找第一个大于 target 的元素的下标,本案例中4 就是第一个大于 target 的元素 ,下标 = 5。
对应方法名格式为
int upper(int[] arr, int target){

//如果都不存在,则返回-1
}

2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,如果不存在,则返回第一个大于 target 的元素下标。本案例中最后一个等于target的下标 = 4。
对应方法名
int floor_upper(int[] arr, int target){
//如果都不存在,则返回-1
}

3.寻找最后一个小于 target 的元素的下标,本案例中 2 则是最后一个小于 target 的,下标 = 1.
对应方法名格式为
int lower(int[] arr, int target){

//如果都不存在,则返回-1
}

4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,如果不存在,则返回最后一个小于 target 的元素的下标。本案例中第一个等于target的下标 = 2。
对应方法名格式为
int floor_lower(int[] arr, int target){

//如果都不存在,则返回-1
}

注意:大家给了模版之后,选择一个适合自己的模版,以后都用这个模版,忘了怎么办?这玩意的区别就是要么是大于,要么是大于等于,你如果记混了,可以随便找一组数据试一下,就能分辨出来了,我笔试时都这样干,,,

答案来了,具体答案看这篇文章:4种二分查找模版讲解

共以下 17 个回答

  • ppopp 普通 2023年8月28日 上午12:29

    /*本次打卡的任务很简单,就是给出四种变形二分查找的模版代码,并且给出了对应的方法名字。

    比如对于一个有序数组

    arr = [1,2,3,3,3,4,5,5,7],target = 3,那么
    */

    /*1.寻找第一个大于 target 的元素的下标,本案例中4 就是第一个大于 target 的元素 ,下标 = 5。
    对应方法名格式为
    int upper(int[] arr, int target){

    //如果都不存在,则返回-1
    }
    */
    int upper(vector arr, int target){
    int len = arr.size();
    int left = 0, right = len – 1;

    if(arr[left] > target || arr[right] < target){
        return -1;
    }
    
    while(left < right){
        int mid = left + (left + right) / 2;
        if(nums[mid] == target){
            left = mid + 1;
        }else if(nums[mid < target]){
            left = mid + 1;
        }else if(nums[mid > target]){
            right = mid;
        }
    
    }
    return left;
    

    }

    /*2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,如果不存在,则返回第一个大于 target 的元素下标。本案例中最后一个等于target的下标 = 4。
    对应方法名
    int floor_upper(int[] arr, int target){
    //如果都不存在,则返回-1
    }
    */

    int floor_upper(vector arr, int target){
    int len = arr.size();
    int left = 0, right = len – 1;

    if(arr[left] > target || arr[right] < target){
        return -1;
    }
    
    while(left < right){
        int mid = left + (left + right) / 2;
        if(nums[mid] == target){
            left = mid + 1;
        }else if(nums[mid < target]){
            left = mid + 1;
        }else if(nums[mid > target]){
            right = mid;
        }
    
    }
    
    if(left - 1 >= 0 && arr[left] > target) return left - 1;
    return left;
    

    }

    /*3.寻找最后一个小于 target 的元素的下标,本案例中 2 则是最后一个小于 target 的,下标 = 1.
    对应方法名格式为
    int lower(int[] arr, int target){
    //如果都不存在,则返回-1
    }
    */

    int lower(vector arr, int target){
    int len = arr.size();
    int left = 0, right = len – 1;

    if(arr[left] > target || arr[right] < target){
        return -1;
    }
    
    while(left < right){
        int mid = left + (left + right) / 2;
        if(nums[mid] == target){
            right = mid - 1;
        }else if(nums[mid < target]){
            left = mid;
        }else if(nums[mid > target]){
            right = mid - 1;
        }
    
    }
    return left;
    

    }

    /*4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,如果不存在,则返回最后一个小于 target 的元素的下标。本案例中第一个等于target的下标 = 2。
    对应方法名格式为
    int floor_lower(int[] arr, int target){

    //如果都不存在,则返回-1
    }*/

    int lower(vector arr, int target){
    int len = arr.size();
    int left = 0, right = len – 1;

    if(arr[left] > target || arr[right] < target){
        return -1;
    }
    
    while(left < right){
        int mid = left + (left + right) / 2;
        if(nums[mid] == target){
            right = mid - 1;
        }else if(nums[mid < target]){
            left = mid;
        }else if(nums[mid > target]){
            right = mid - 1;
        }
    
    }
    
    if(arr[left] < target) return left + 1;
    return left;
    

    }

    0 赞同 0 条回复
  • doordie. 普通 2023年8月14日 上午9:34

    打卡

    0 赞同 0 条回复
  • CaCO3 永久会员 2023年7月31日 上午10:02

    ”’java
    //寻找第一个大于target的元素
    int upper(int[] arr,int target){
    //如果都不存在,则返回-1
    int l = 0;
    int r = arr.length – 1;
    if(arr[r] <= target){
    return -1;
    }
    while(l < r){
    int mid = (l + r)/2;
    if(arr[mid] <= target){
    l = mid + 1;
    }else{
    r = mid;
    }
    }
    return l;
    }
    //返回最后一个等于target的元素下标,否则返回第一个大于target的元素
    int floor_upper(int[] arr,int target){
    //如果都不存在,则返回-1
    int l = 0;
    int r = arr.length – 1;
    if(arr[r] < target){
    return -1;
    }
    while(l < r){
    int mid = (l + r)/2;
    if(arr[mid] <= target){
    l = mid + 1;
    }else{
    r = mid;
    }
    }
    if(l-1 >= 0 && arr[l-1] target){
    return l – 1;
    }
    return l;
    }

    //寻找最后一个小于target的元素的下标
    int lower(int[] arr,int target){
    int l = 0;
    int r = arr.length – 1;
    if(arr[l] >= target){
    return -1;
    }
    while(l < r){
    int mid = (l+r+1)/2;
    if(arr[mid] < target){
    l = mid;
    }else{
    r = mid – 1;
    }
    }
    return l;
    }
    //返回第一个等于target的元素下标,若不存在则返回最后一个小于target元素的下标
    int floor_lower(int[] arr,int target){
    int l = 0;
    int r = arr.length – 1;
    if(arr[l] > target){
    return -1;
    }
    while(l < r){
    int mid = (l + r + 1)/2;
    if(arr[mid] < target){
    l = mid;
    }else{
    r = mid – 1;
    }
    }
    if(l+1 < arr.length && arr[l+1]target){
    return l+1;
    }
    return l;
    }

    ”’

    0 赞同 0 条回复
  •  普通 2023年7月27日 下午10:28

    c++ 模版主要是界限

    0 赞同 0 条回复
  • 枫梓。 普通 2023年7月27日 下午3:03
    public:
        BinarySearch(int a) {target = a;}
    
        int findupper() {
            int lt = 0;
            int rt = arr.size() - 1;
            while(lt < rt) {
                int mid = (rt - lt) / 2 + lt;
                if(arr[mid] > target) {
                    rt = mid;
                } else if(arr[mid] == target) {
                    lt = mid + 1;
                } else {
                    lt = mid + 1;
                }
            }
            cout << lt << " " << arr[lt] << endl;
            return lt;
        }
    
        int findequal() {
            int lt = 0;
            int rt = arr.size() - 1;
            while(lt < rt) {
                int mid = (rt - lt + 1) / 2 + lt;
                if(arr[mid] <= target) {
                    lt = mid;
                } else {
                    rt = mid - 1;
                }
            }
            cout << lt << " " << arr[lt] << endl;
            return lt;
        }
    
        int findlower() {
            int lt = 0;
            int rt = arr.size() - 1;
            while(lt < rt) {
                int mid = (rt - lt + 1) / 2 + lt;
                if(arr[mid] < target) {
                    lt = mid;
                } else if(arr[mid] == target) {
                    rt = mid - 1;
                } else {
                    rt = mid - 1;
                }
            }
            cout << lt << " " << arr[lt] << endl;
            return lt;
        }
    int find1equal() {
            int lt = 0;
            int rt = arr.size() - 1;
            while(lt < rt) {
                int mid = (rt - lt) / 2 + lt;
                if(arr[mid] < target) {
                    lt = mid + 1;
                } else {
                    rt = mid;
                }
            }
            cout << lt << " " << arr[lt] << endl;
            return lt;
        }
    
    private:
        vectorarr = {0,1,2,3,3,3,4,5,6};
        int target;
    };
    

    二分查找

    0 赞同 0 条回复
  • 北辰 普通 2023年7月26日 下午8:20
    public class 四种二分查找模板 {
    
        public static void main(String[] args) {
            int[] arr = {1,2,3,3,3,4,5,5,7};
            int target = 3;
            System.out.println(upper(arr,target));
            System.out.println(floor_upper(arr,target));
            System.out.println(lower(arr,target));
            System.out.println(floor_lower(arr,target));
        }
    
        //1.寻找第一个大于 target 的元素的下标
        public static int upper(int[] arr,int target) {
            int n = arr.length;
            int l = 0,r=n-1;
            while(l<r) {
                int mid = l+(r-l)/2;
                if(arr[mid]<=target) l=mid+1;
                else r=mid;
            }
            return arr[l]>target?l:-1;
        }
    
        //2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,
        //如果不存在,则返回第一个大于 target 的元素下标。
        public static int floor_upper(int[] arr,int target) {
            int n = arr.length;
            int l = 0,r=n-1;
            while(l<r) {
                int mid = l+(r-l)/2;
                if(arr[mid]<target) l=mid+1;
                if(arr[mid]>=target)r = mid;
            }
            if(arr[l]==target) {
                while(arr[l]==target) {
                    l++;
                }
                return l-1;
            }
            return l;
        }
    
        //3.寻找最后一个小于 target 的元素的下标
        public static int lower(int[] arr,int target) {
            int n = arr.length;
            int l=0,r=n-1;
            while(l<r) {
                int mid = l+(r-l)/2;
                if(arr[mid]<target) l = mid+1;
                else r=mid;
            }
            return l-1>=0?l-1:-1;
        }
    
        //4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,如果不存在,则返回最后一个小于 target 的元素的下标
        public static int floor_lower(int[] arr,int target) {
            int n = arr.length;
            int l=0,r=n-1;
            while(l<r) {
                int mid = l+(r-l)/2;
                if(arr[mid]<target) l = mid+1;
                else r=mid;
            }
            if(arr[l]==target) {
                return l;
            }
    //      System.out.println(l);
            return l-1;
        }
    }
    
    0 赞同 0 条回复
  • 土豆芋泥包_ 普通 2023年7月25日 下午8:49

    代码

    public class erfenchazhao {
        public static void main(String[] args) {
            int[] arr = new int[]{1,2,3,3,3,4,5,5,7};
            int target = 3;
            int index = 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;
            }
            while(l<r){
                int mid = (r-l)/2+l;
                if(arr[mid]>target){
                    r = mid;
                }else if(arr[mid]==target){
                    l = mid+1;
                }else{
                    l = mid+1;
                }
            }
            return l;
        }
    
        // 2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,
        public static int floor_upper(int[] arr, int target){
            int l=0;
            int r = arr.length-1;
            if(arr[r]<target){
                return -1;
            }
            while(l<r){
                int mid = (r-l)/2 + l;
                if(arr[mid]>target){
                    r = mid;
                }else if(arr[mid]==target){
                    l = mid + 1;
                }else{
                    l = mid + 1;
                }
            }
            if(l-1>=0 && arr[l-1]==target){
                return l-1;
            }
            return l;
        }
    
        //3.寻找最后一个小于 target 的元素的下标
        public static int lower(int[] arr, int target){
            int l=0;
            int r = arr.length-1;
            if(arr[l]>=target){
                return -1;
            }
            while(l<r){
                int mid = (r-l+1)/2+l;
                if(arr[mid]>target){
                    r = mid - 1;
                } else if (arr[mid]==target) {
                    r = mid -1;
                } else {
                    l = mid;
                }
            }
            return l;
        }
    
        // 4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,
        public static int floor_lower(int[] arr, int target){
            int l=0;
            int r = arr.length-1;
            if(arr[l]>=target){
                return -1;
            }
            while(l<r){
                int mid = (r-l+1)/2+l;
                if(arr[mid]>target){
                    r = mid - 1;
                } else if (arr[mid]==target) {
                    r = mid - 1;
                }else{
                    l = mid;
                }
            }
            if(l+1<arr.length && arr[l+1]==target){
                return l+1;
            }
            return l;
        }
    }
    
    0 赞同 0 条回复
  • 刹那芳间 普通 2023年7月25日 下午12:40
    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;
        }
    }
    
    0 赞同 0 条回复
  • CKX 普通 2023年7月24日 下午3:13
    package main
    
    import "fmt"
    
    func main() {
        arr := []int{1, 2, 3, 3, 3, 4, 5, 5, 7}
        target := 3
        fmt.Println(upper(arr, target))
        fmt.Println(floor_upper(arr, target))
        fmt.Println(lower(arr, target))
        fmt.Println(floor_lower(arr, target))
    
    }
    
    /*
    *
    1.寻找第一个大于 target 的元素的下标,本案例中4 就是第一个大于 target 的元素 ,下标 = 5。
    */
    func upper(arr []int, target int) int {
        l := 0
        r := len(arr) - 1
        //特殊情况
        if arr[r] <= target {
            return -1
        }
        for l < r {
            mid := (r + l) / 2
            if arr[mid] > target {
                r = mid
            } else if arr[mid] == target {
                l = mid + 1
            } else {
                l = mid + 1
            }
        }
        return l
    }
    
    /*
    *
    2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标
    如果不存在,则返回第一个大于 target 的元素下标。
    本案例中最后一个等于target的下标 = 4。
    */
    func floor_upper(arr []int, target int) int {
        l := 0
        r := len(arr) - 1
        //特殊情况
        if arr[r] <= target {
            return -1
        }
        for l < r {
            mid := (r + l) / 2
            if arr[mid] > target {
                r = mid
            } else if arr[mid] == target {
                l = mid + 1
            } else {
                l = mid + 1
            }
        }
        if l-1 >= 0 && arr[l-1] == target {
            return l - 1
        }
        return l
    }
    
    /*
    *
    3.寻找最后一个小于 target 的元素的下标,本案例中 2 则是最后一个小于 target 的,下标 = 1.
    */
    func lower(arr []int, target int) int {
        l := 0
        r := len(arr) - 1
        //特殊情况
        if arr[r] <= target {
            return -1
        }
        for l < r {
            // r = 1, l = 0, mid = 0
            mid := (r+l)/2 + 1
            //[l, mid, r]
            if arr[mid] > target {
                r = mid - 1
            } else if arr[mid] == target {
                r = mid - 1
            } else {
                l = mid
            }
        }
        return l
    }
    
    /**
    4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,
    如果不存在,则返回最后一个小于 target 的元素的下标。
    本案例中第一个等于target的下标 = 2。
    */
    
    func floor_lower(arr []int, target int) int {
        l := 0
        r := len(arr) - 1
        //特殊情况
        if arr[r] <= target {
            return -1
        }
        for l < r {
            // r = 1, l = 0, mid = 0
            mid := (r+l)/2 + 1
            //[l, mid, r]
            if arr[mid] > target {
                r = mid - 1
            } else if arr[mid] == target {
                r = mid - 1
            } else {
                l = mid
            }
        }
        if l+1 < len(arr) && arr[l+1] == target {
            return l + 1
        }
        return l
    }
    
    
    0 赞同 0 条回复
  • 人生何处不青山 普通 2023年7月23日 下午11:03

    二分主要还是边界太恶心了

    “`c++
    #include
    #include
    using namespace std;

    const int N = 1e5 + 10;
    int n,m;
    int q[N];

    int main() {
    cin >> n >> m;
    for(int i = 0; i < n; i ++ ) scanf(“%d”,&q[i]);
    while(m–) {
    int x;
    cin >> x;
    int l = 0, r = n – 1;
    while(l < r) {
    int mid = (l + r) >> 1;
    if(q[mid] > x) {
    r = mid ;
    }else if (q[mid] x) {
    r = mid;
    } else {
    l = mid + 1;
    }
    }
    if(q[l] != x) {
    cout << “-1 -1” << endl;
    } else {
    cout << l <<‘ ‘;
    r = n-1;
    while(l < r) {
    int mid = (l + r + 1) >> 1;
    if(q[mid] < x) {
    l = mid;
    } else if (q[mid]
    x) {
    l = mid;
    } else {
    r = mid -1;
    }
    }
    cout << l << endl;
    }
    }

    return 0;
    

    }

    “`

    0 赞同 0 条回复
  • 今天你刷题了嘛 普通 2023年7月23日 下午9:58
    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;
        }
    }
    
    0 赞同 0 条回复
  • Mby 普通 2023年7月23日 下午7:18
    //一
        //1.寻找第一个大于 target 的元素的下标,案例:arr[1, 2,3,3,3,4,5,5,7], target = 3。
        public static int binarySearchBasic(int[] a, int target){
            int i = 0, j = a.length - 1;//设置指针和初值
            while(i <= j){//范围内有值
                int m = (i + j) >>> 1;//采用右移运算符 相当于除二再向下取整 能解决符号位问题
                if(target < a[m]){//目标在左边
                    j = m - 1;
                }else if(a[m] < target){//目标在右边
                    i = m + 1;
                }else{//找到
                        return m;
                }
            }
            return -1;
        }
    
        //二
        //2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,
        public static int binarySearchRightMost(int[] a, int target){
            int i = 0,j = a.length - 1;
            while(i <= j){
                int m = (i + j) >>> 1;
                if(target < a[m]){
                    j = m - 1;
                }else{
                    i = m + 1;
                }
            }
            return i - 1;
        }
        //三
        //3.寻找最后一个小于 target 的元素的下标
        public static int lower (int[] a, int target){
            int i = 0;
            int j = a.length - 1;
            //判断特殊情况
            if(a[i] >= target){
                return -1;
            } 
            while(i < j){
                int m = (r - l + 1) / 2 + 1;
                if(a[m] >= target){
                    j = m - 1;
                }else{
                    i = m;
                }
            }
            return i;
        }
        //四
        // 4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,
        // 如果不存在,则返回最后一个小于 target 的元素的下标
        public static int floor_lower(int[] a, int target){
            int i = 0;
            int j = a.length - 1;
            //判断特殊情况
            if(arr[i] > target){
                return -1;
            }
            while(i < j){
                int m = (r - i + 1) / 2 + 1;
                if(a[m] >= target){
                    r = m - 1;
                }else{
                    i = m;
                }
            }
            if(i + 1 < a.length && a[i + 1] == target){
                return i + 1;
            }
            return i;
        }
    
    
    0 赞同 0 条回复
  • Marshan 普通 2023年7月23日 下午4:45

    #include
    #include
    using namespace std;

    //1.寻找第一个大于 target 的元素的下标,案例:arr[1, 2,3,3,3,4,5,5,7], target = 3。
    

    int upper(vector arr,int target){
    int l = 0;
    int r = arr.size()-1;
    if(arr[r] <= target){
    return -1;
    }
    while(l < r){
    int mid = (r – l) / 2 + l;
    if(arr[mid] > target){
    r = mid;
    }
    else if(arr[mid] target){
    l = mid + 1;
    }
    else{//arr[mid] < target
    l = mid + 1;
    }
    }

    return l;
    

    }
    //2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,
    // 如果不存在,则返回第一个大于 target 的元素下标
    int floor_upper(vector arr,int target){
    int l = 0;
    int r = arr.size()-1;
    if(arr[r] < target){
    return -1;
    }
    while(l < r){
    int mid = (r – l) / 2 + l;
    if(arr[mid] > target){
    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 的元素的下标
    int lower(vector
    arr,int target){
    int l = 0;
    int r = arr.size()-1;
    if(arr[l] >= target){
    return -1;
    }
    while(l < r){
    int mid = (r – l + 1) / 2 + l;
    if(arr[mid] > target){
    r = mid – 1;
    }
    else if(arr[mid] target){
    l = mid – 1;
    }
    else{//arr[mid] < target
    l = mid;
    }
    }

    return l;
    

    }
    // 4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,
    // 如果不存在,则返回最后一个小于 target 的元素的下标
    int floor_lower(vector arr,int target){
    int l = 0;
    int r = arr.size()-1;
    if(arr[l] >= target){
    return -1;
    }
    while(l < r){
    int mid = (r – l + 1) / 2 + l;
    if(arr[mid] > target){
    r = mid – 1;
    }
    else if(arr[mid] target){
    l = mid – 1;
    }
    else{//arr[mid] < target
    l = mid;
    }
    }
    if(l + 1 < arr.size() && arr[l+1]
    target){
    return l – 1;
    }
    return l;
    }

    0 赞同 0 条回复
  • AD钙奶 普通 2023年7月22日 下午3:35

    写二分,注意遵循 循环不变量 原则,即定义了一套边界标准,无论是左闭右闭,还是左闭右开之后,就不再变化。

    /**
     *  arr = [1,2,3,3,3,4,5,5,7],target = 3
     *  寻找第一个大于 target 的元素的下标
     */
    public static int upper(int[] arr, int target) {
        int l = 0, r = arr.length - 1;
        if(arr[r] <= target) return -1;
        while(l <= r) {
            int mid = l + r >> 1;
            if(arr[mid] > target) {
                r = mid - 1;
            }
            else {
                l = mid + 1;
            } 
        }
        return l;
    }
    /**
     *  arr = [1,2,3,3,3,4,5,5,7],target = 3
     *  如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,
     *  如果不存在,则返回第一个大于 target 的元素下标。
     */
     public static int floor_upper(int[] arr, int target) {
        // 先找到第一个大于target的元素下标
        int tmp = upper(arr,target); 
        // 再看它的前一位是否等于target
        if(tmp - 1 >= 0 && arr[tmp - 1] == target) {
            return tmp - 1;
        }
        return tmp;
    }
    
    /**
     *  arr = [1,2,3,3,3,4,5,5,7],target = 3
     *  寻找最后一个小于 target 的元素的下标
     */
     public static int lower(int[] arr, int target) {
        int l = 0, r = arr.length - 1;
        if(arr[l] >= target) return -1;
        while(l <= r) {
            int mid = l + r >> 1;
            if(arr[mid] >= target) {
                r = mid - 1;
            }
            else {
                l = mid + 1;
            } 
        }
        return l;
    }
    
    /**
     *  arr = [1,2,3,3,3,4,5,5,7],target = 3
     *  如果数组中存在元素等于 target,则返回第一个等于target 的下标,
     *  如果不存在,则返回最后一个小于 target 的元素的下标。
     */
     public static int floor_lower(int[] arr, int target) {
        // 先找到最后一个小于 target 的元素的下标
        int tmp = lower(arr,target);
        // 再判断往后一个元素是否等于target
        if(tmp < arr.length - 1 && arr[tmp + 1] == target) {
            return tmp + 1;
        }
        return tmp;
    }
    
    0 赞同 0 条回复
  • mpweixin用户 普通 2023年7月22日 上午10:18
    public static int sort(int[] arr, int target) {
             //二分模板
            //1 2 3 3 3 4 5 5 7   3
            int left = -1, right = arr.length;
            while (left+1 < right) {
                int middle = left + (right-left)/2;
                if (arr[middle] > target) {
                    right = middle;
                } else {
                    left = middle;
                }
            }
            if (right >= arr.length) {
                return -1;
            }
            return right;
        }
    
        public static int sort2(int[] arr, int target) {
            int left = -1, right = arr.length;
            while (left+1 < right) {
                int middle = left+(right-left)/2;
                if (arr[middle] <= target) {
                    left = middle;
                } else {
                    right = middle;
                }
            }
            if (arr[left]==target && left!=-1) {
                return left;
            } else {
                return sort(arr, target);
            }
        }
    
        public static int sort3(int[] arr, int target) {
            int left = -1, right = arr.length;
            while (left+1 < right) {
                int middle = left + (right-left)/2;
                if (arr[middle] < target) {
                    left = middle;
                } else {
                    right = middle;
                }
            }
            return left;
        }
    
        //1 2 3 3 3 4 5 5 7   3
        public static int sort4(int[] arr, int target) {
            int left = -1, right = arr.length;
            while (left+1 < right) {
                int middle = left+(right-left)/2;
                if (arr[middle] >= target) {
                    right = middle;
                } else {
                    left = middle;
                }
            }
            if (right!=-1&&arr[right]==target) {
                return right;
            } else {
                return sort3(arr, target);
            }
        }
    
    1 赞同 0 条回复
  • #00456B 普通 2023年7月21日 下午7:46
    #include<iostream>
    #include<string>
    #include<algorithm>
    using namespace std;
    
    //寻找第一个大于target的元素的下标
    //本案例中4就是第一个大于target的元素,下标=5
    int upper(vector<int> arr, int target){
        int left = 0;
        int right = arr.size() - 1;
        if(arr[right] <= target){
            return -1;
        }
        while(left <= right){
            int mid = left + (right - left)/2;
            if(arr[mid] > target){
                right = mid - 1;
            }
            else if(arr[mid] < target){
                left = mid + 1;
            }
            else{
                //要比target大
                left = mid + 1;
            }
        }
        return left;
    }
    
    //如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,如果不存在,则返回第一个大于 target 的元素下标。
    //本案例中最后一个等于target的下标 = 4。
    int floor_upper(vector<int> arr, int target){
        //相当于在upper的基础上再向前一位做判断,是否等于target
        int temp = upper(arr, target);
        if(temp - 1 >= 0 && arr[temp - 1] <span class="text-highlighted-inline" style="background-color: #fffd38;"> target){
            return temp - 1;
        }
        return temp;
    }</span>
    
    //寻找最后一个小于 target 的元素的下标
    //本案例中 2 则是最后一个小于 target 的,下标 = 1.
    int lower(vector<int> arr, int target){
        int l = 0;
        int r = arr.size() - 1;
        if(arr[l] >= target){
            return -1;
        }
        while(l <= r){
            int mid = l + (r - l)/2;
            if(arr[mid] > target){
                r = mid - 1;
            }
            else if(arr[mid] < target){
                l = mid + 1;
            }
            else{
                r = mid - 1;
            }
        }
        return r;
    }
    
    //如果数组中存在元素等于 target,则返回第一个等于target 的下标,如果不存在,则返回最后一个小于 target 的元素的下标。
    //本案例中第一个等于target的下标 = 2。
    int floor_lower(vector<int> arr, int target){
        int temp = lower(arr, target);
        if(temp + 1 < arr.size() && arr[temp + 1] <span class="text-highlighted-inline" style="background-color: #fffd38;"> target){
            return temp + 1;
        }
        return temp;
    }</span>
    
    int main(){
        vector<int> arr = {1,2,3,3,3,4,5,6,7};
        int target = 3;
        int index1 = upper(arr, target);
        cout<<"upper: index = "<<index1<<" val = "<<arr[index1]<<endl;
        int index2 = floor_upper(arr, target);
        cout<<"floor_upper: index = "<<index2<<" val = "<<arr[index2]<<endl;
        int index3 = lower(arr, target);
        cout<<"lower: index = "<<index3<<" val = "<<arr[index3]<<endl;
        int index4 = floor_lower(arr, target);
        cout<<"floor_lower: index = "<<index4<<" val = "<<arr[index4]<<endl;
    }
    
    0 赞同 0 条回复
  • 阿尚 普通 2023年7月21日 下午5:09
    public class BinarySearch {
        //寻找第一个大于 target 的元素的下标,本案例中4 就是第一个大于 target 的元素 ,下标 = 5。
        public static int upper(int[] arr, int target){
            if(arr == null || arr.length == 0) {
                return -1;
            }
            //如果都不存在,则返回-1
            int l = 0;
            int r = arr.length - 1;
    
            while(l <= r){
                int midIdx = l + ((r - l) >> 1);
    
                if(target >= arr[midIdx]){
                    l = midIdx + 1;
                }else{
                    r = midIdx - 1;
                }
            }
    
            return l == arr.length ? -1 : l;
        }
    
        //如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,如果不存在,则返回第一个大于 target 的元素下标
        public static int floor_upper(int[] arr, int target){
            if(arr == null || arr.length == 0) {
                return -1;
            }
            //如果都不存在,则返回-1
            int l = 0;
            int r = arr.length - 1;
    
            while(l <= r){
                int midIdx = l + (r - l) / 1;
    
                if(target >= arr[midIdx]){
                    l = midIdx + 1;
                }else{
                    r = midIdx - 1;
                }
            }
    
            if(arr[r] == target){
                return r;
            }
            return l == arr.length ? -1 : l;
        }
    
        //寻找最后一个小于 target 的元素的下标,本案例中 2 则是最后一个小于 target 的,下标 = 1.
        public static int lower(int[] arr, int target){
            if(arr == null || arr.length == 0) {
                return -1;
            }
            //如果都不存在,则返回-1
            int l = 0;
            int r = arr.length - 1;
    
            while(l <= r){
                int midIdx = l + ((r - l) >> 1);
    
                if(target <= arr[midIdx]){
                    r = midIdx - 1;
                }else{
                    l = midIdx + 1;
                }
            }
    
            return r < 0 ? -1 : r;
        }
    
        //如果数组中存在元素等于 target,则返回第一个等于target 的下标,如果不存在,则返回最后一个小于 target 的元素的下标
        public static int floor_lower(int[] arr, int target){
            if(arr == null || arr.length == 0) {
                return -1;
            }
            //如果都不存在,则返回-1
            int l = 0;
            int r = arr.length - 1;
    
            while(l <= r){
                int midIdx = l + ((r - l) >> 1);
    
                if(target <= arr[midIdx]){
                    r = midIdx - 1;
                }else{
                    l = midIdx + 1;
                }
            }
    
            if(arr[l] == target){
                return l;
            }
            return r < 0 ? -1 : r;
        }
    
        public static void main(String[] args) {
            //arr = [1,2,3,3,3,4,5,5,7],target = 3
            int[] arr = {1,2,3,3,3,4,5,5,7};
            int target = 3;
    
            int firstMaxTarget = upper(arr, target);
            System.out.println("upper:index = " + firstMaxTarget);
    
            int lastEqualTarget = floor_upper(arr, target);
            System.out.println("floor_upper:index = " + lastEqualTarget);
    
            int lastMinTarget = lower(arr, target);
            System.out.println("lower:index = " + lastMinTarget);
    
            int firstEquelTarget = floor_lower(arr, target);
            System.out.println("floor_lower:index = " + firstEquelTarget);
    
        }
    }
    
    
    0 赞同 0 条回复

# 回答此问题

后才能回答