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

本问题对应课程链接:剑指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种二分查找模版讲解

共以下 19 个回答

  • YOLO 普通 2024年4月12日 下午8:35
    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;
            }
            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){
                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的元素的下标,案例:arr[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[r] >= target){
            return -1;
        }
        //[l,r],在二分查找的过程中,不断缩小我们的查找范围,直到查找范围里面只有一个元素,那个就是我们要找的元素
        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{//arr[mid] < target
                l = mid;
            }
        }
        return l;
    }
    4、//若数组中存在等于target的元素,则返回最后一个等于target的元素的下标
    //如果不存在,则返回第一个大于target的元素下标
    //案例:arr[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[r] > target){
            return -1;
        }
        //[l,r],在二分查找的过程中,不断缩小我们的查找范围,直到查找范围里面只有一个元素,那个就是我们要找的元素
        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{//arr[mid] < target
                l = mid;
            }
        }
        if(l + 1 <= arr.length && arr[l - 1] == target){
            return l + 1;
        }
    
        return l;
    }
    
    0 赞同 0 条回复
  • =.= 普通 2024年3月30日 下午2:50

    class Solution {
    public int[] searchRange(int[] nums, int target) {
    int n = nums.length;
    int[] ans = new int[2];

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

    }

    时间复杂度

    0 赞同 0 条回复
  • 南梁陈庆之 普通 2024年3月23日 上午1:16

    四种二分查找四种情况
    1、查找大于匹配的第一个元素
    2、查找最后一个等于匹配的元素,如果找不到找到大于匹配的元素
    3、查找小于匹配的最后一个元素
    4、查找第一个匹配的元素,如果找不到则找小于匹配元素的元素

    package com.playoffer;
    
    /**
     * User: 胡兴
     * Date: 2024/3/23
     * Description:
     */
    public class BinarTest {
    
    
        int upper(int[] arr, int target){
    
            //如果都不存在,则返回-1
    
            int l = 0, r = arr.length - 1;
            if (arr[r] < target) {
                return -1;
            }
            while (l < r) {
                int m = (r - l) / 2 + l;
                if (arr[m] > target) {
                    r = m;
                } else if (arr[m] == target) {
                    l = m + 1;
                } else { // arr[m] < target
                    l = m + 1;
                }
            }
            return l;
        }
    
        int floor_upper(int[] arr, int target){
            int l = 0, r = arr.length - 1;
            if (arr[r] < target) {
                return -1;
            }
            while (l < r) {
                int m = (r - l) / 2 + l;
                if (arr[m] > target) {
                    r = m;
                } else if (arr[m] == target) {
                    l = m + 1;
                } else { // arr[m] < target)
                    l = m + 1;
                }
            }
            if (l - 1 >= 0 && arr[l - 1] == target) {
                return l - 1;
            }
            return l;
        }
    
        // 寻找最后一个小于 target 的元素的下标,本案例中 2 则是最后一个小于 target 的,下标 = 1.
        int lower(int[] arr, int target){
            int l = 0, r = arr.length - 1;
            if (arr[l] >= target) {
                return  - 1;
            }
            while (l < r) {
                int m = (r - l + 1) / 2 + l;
                if (arr[m] > target) {
                    r = m - 1;
                } else if (arr[m] == target) {
                    r = m - 1;
                } else { // arr[m] < target
                    l = m;
                }
                System.out.println(l + "," + m + "," + r);
            }
            return l;
        }
    
        // 如果数组中存在元素等于 target,则返回第一个等于target 的下标,
        // 如果不存在,则返回最后一个小于 target 的元素的下标。本案例中第一个等于target的下标 = 2。
        int floor_lower(int[] arr, int target){
            int l = 0, r = arr.length - 1;
            if (arr[l] >= target)
                return -1;
            while (l < r) {
                int m = (r - l + 1) / 2 + l;
                if (arr[m] > target) {
                    r = m - 1;
                } else if (arr[m] == target) {
                    r = m - 1;
                } else {
                    l = m;
                }
                System.out.println(l + "," + m + "," + r);
            }
            if (l + 1 < arr.length && arr[l + 1] == target) {
                return l + 1;
            }
            return l;
        }
    
        public static void main(String[] args) {
            int[] arr = new int[]{1,2,3,3,3,4,5,5,7};
            int target = 3;
    
            BinarTest obj = new BinarTest();
            int upper = obj.floor_lower(arr, target);
            System.out.println(upper); // 3
    
        }
    
    
    }
    
    
    0 赞同 0 条回复
  • Raphtalia. 普通 2024年3月19日 下午10:45

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

    //先找第一个大于的,然后看前一个。
    int l = 0, r = arr.size() – 1;
    if(nums[r] <= target) return -1;
    while(l < r){
    int mid = l + r >> 1;
    if(arr[mid] > target){
    //[l,mid]
    r = mid;
    }
    else if(arr[mid] target){
    //(mid,r]
    l = mid + 1;
    }
    else{
    //(mid,r]
    l = mid + 1;
    }
    if(nums[l – 1]
    target && l > 0) return l – 1;
    return l;
    }
    int l = 0, r = arr.size() – 1;
    if(nums[r] <= target) return -1;
    while(l < r){
    int mid = l + r >> 1;
    if(arr[mid] > target){
    //[l,mid)
    r = mid – 1;
    }
    else if(arr[mid] target){
    //[l, mid)
    r = mid – 1;
    }
    else{
    //[l,mid]
    l = mid;
    }
    return l;
    }
    int l = 0, r = arr.size() – 1;
    if(nums[r] <= target) return -1;
    while(l < r){
    int mid = l + r >> 1;
    if(arr[mid] > target){
    //[l,mid)
    r = mid – 1;
    }
    else if(arr[mid]
    target){
    //[l, mid)
    r = mid – 1;
    }
    else{
    //[l,mid]
    l = mid;
    }
    if(arr[l + 1] target && l < arr.size()) return l + 1;
    return l;
    }

    0 赞同 0 条回复
  • kfaebot 普通 2024年3月19日 下午10:32
    class Solution {
    public:
        //寻找第一个大于target的元素
        int search_upper(vector<int>& nums, int target) {
            int left=0;
            int right=nums.size()-1;
    
            if(nums[r]<=target){
                return -1;
            }
    
            while(left<right){
                int middle=(left+right)/2;
                if(nums[middle]>target){
                    right=middle;
                }
                else if(nums[middle]<target){
                    left=middle+1;
                }
                esle if(nums[middle]==target){
                    left=middle+1;
                }
            }
            return left;
        }
        //寻找最后一个小于target的元素
        int search_lower(vector<int>& nums, int target){
            int left=0;
            int right=nums.size()-1;
    
            if(nums[left]>=target){
                return -1;
            }
    
            while(left<right){
                //注意这里要加1
                int middle=(left+right+1)/2;
    
                if(nums[middle]>target){
                    right=middle-1;
                }
                else if(nums[middle]<target){
                    left=middle;
                }
                else if(nums[middle]==target){
                    right=middle-1;
                }
            }
            return left;
        }
    
        //寻找第一个等于target的下标,若不存在,返回最后一个小于target元素的下标,若都不存在返回-1
        int search_first_target(vector<int>& nums, int target){
            int left=0;
            int right=nums.size()-1;
    
            //判断极端情况
            if(nums[left]>target){
                return -1;
            }
    
            while(left<right){
                int middle=(left+right+1)/2;
                if(nums[middle]>target){
                    right=middle-1;
                }
                else if(nums[middle]<target){
                    left=middle;
                }
                else if(nums[middle]==target){
                    right=middle-1;
                }
            }
            if(left+1<nums.size()&&nums[left+1]==target){
                return left+1;
            }
            return left;
        }
    
        //寻找最后一个等于target的下标,若不存在,返回第一个大于target元素的下标,若都不存在返回-1
        int search_last_target(vector<int>& nums, int target){
            int left=0;
            int right=nums.size()-1;
    
            //极端情况
            if(nums[r]<target){
                return -1;
            }
            while(left<right){
                int middle=(left+right)/2;
                if(nums[middle]>target){
                    right=middle;
                }
                else if(nums[middle]<target){
                    left=middle+1;
                }
                else if(nums[middle]==target){
                    left=middle+1;
                }
            }
            if(left-1>=0&&nums[left-1]==target){
                return left-1;
            }
            return left;
        }
    };
    
    0 赞同 0 条回复
  • 神经蛙 普通 2024年3月16日 下午12:05

    思路:
    如果是找第一个则向下取整,mid = left + (right- left)/2
    如果是找最后一个则向上取整,mid = left +(right -left +1)/2

    0 赞同 0 条回复
  • 方铎码农 普通 2024年3月16日 上午11:32
    import java.util.Arrays;
    import java.util.Scanner;
    
    public class Main {
    
        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_upper(arr, target);
            System.out.println("index = "+ index + ", value = " + arr[index]);
        }
    
        private 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;
        }
    
       private 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 {
                   l = mid + 1;
               }
           }
    
           if(l - 1 >= 0 && arr[l-1] == target) return l - 1;
    
           return l;
        }
    
       private 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) / 2 + l;
               if(arr[mid] >= target){
                   r = mid - 1;
               } else {
                   l = mid;
               }
           }
           return l;
       }
    
        private 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 {
                    l = mid;
                }
            }
    
            if(l + 1 < arr.length && arr[l-1] == target) return l + 1;
    
            return l;
        }
    
    
    }
    
    

    打卡

    0 赞同 0 条回复
  • 言之命至 普通 2024年3月15日 下午9:05
      //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;
            // 先判断特殊情况,不存在先判断,while就肯定存在
            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){  //根据第一题,while出来之后 l是第一个大于 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时  注意,如果还 int mid = (r - l) / 2 + l,此时mid = 0,范围不会缩小,就一直循环了,所以需要向上取整, int mid = (r - l + 1) / 2 + l;
    
                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;
                }
            }
            //和题3差不多,注意判断越界
            if(l + 1 < arr.length && arr[l + 1] == target){
                return l + 1;
            }
            return l;
        }
    
    0 赞同 0 条回复
  • 王位詮釋 普通 2024年3月15日 下午1:12
    // 寻找第一个大于target的值的数组下标
        public static int upper(int[] arr, int target) {
            int l = 0;
            int r = arr.length - 1;// 因为会用到r作为数组索引,所以保证不能越界
            if (arr[r] <= target) {
                return -1;
            }
            while (l < r) {// 由于在arr[mid]>target的时候会将r=mid 所以如果循环条件是l<=r的话可能会导致一直死循环
                int mid = l + (r - l) / 2;
                if (arr[mid] > target) {
                    r = mid;// 由于查找的是第一个比target大的元素,因此有可能mid所在的元素就是这个元素,所以这里不能让r=mid-1,而是让r=mid
                } else if (arr[mid] == target) {// 由于是查找第一个比target大的元素,所以在arr[mid]==target的时候 不能返回数组下标,而是继续遍历下一个下标
                    l = mid + 1;
                } else {// arr[mid]<target
                    l = mid + 1;
                }
            }
            return l;
        }
    
        // 如果数组中存在元素等于target,则返回最后一个等于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 = l + (r - l) / 2;
                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;
        }
    
        // 寻找最后一个小于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 = l + (r - l + 1) / 2;
                if (arr[mid] > target) {
                    r = mid - 1;
                } else if (arr[mid] == target) {
                    r = mid - 1;// 由于查找的是第一个小于target的值,所以要尽量往小于target的那半边进行查找
                } else {// arr[mid]<target
                    l = mid;
                }
            }
            return l;
        }
    
        // 如果数组的元素存在值为target的则返回第一个等于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 = l + (r - l + 1) / 2;
                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 条回复
  • 云无深雁影 普通 2024年3月15日 上午11:31

    //第一种
    class Solution {
    public int search(int[] nums, int target) {
    int begin = 0;
    int end = nums.length – 1;
    while(begin <= end){
    int mid = (end + begin)/2;
    if(target nums[mid])
    return mid;
    if(target > nums[mid])
    begin = mid + 1;
    else
    end = mid – 1;
    }
    return -1;
    }
    }
    //第二种
    class Solution {
    public int search(int[] nums, int target) {
    int begin = 0;
    int end = nums.length – 1;
    while(begin <= end){
    int mid = (end + begin)/2;
    if(target
    nums[mid])
    break;
    if(target > nums[mid])
    begin = mid + 1;
    else
    end = mid – 1;
    }
    return mid>=nums.length ? -1 : mid+1;
    }
    }
    //第三种

    class Solution {
    public int search(int[] nums, int target) {
    int begin = 0;
    int end = nums.length – 1;
    while(begin <= end){
    int mid = (end + begin)/2;
    if(target nums[mid])
    break;
    if(target > nums[mid])
    begin = mid + 1;
    else
    end = mid – 1;
    }
    return mid<1 ? -1 : mid - 1;
    }
    }
    //第四种
    class Solution {
    public int search(int[] nums, int target) {
    int begin = 0;
    int end = nums.length - 1;
    while(begin <= end){ int mid = (end + begin)/2; if(target == nums[mid]) return mid; if(target > nums[mid])
    begin = mid + 1;
    else
    end = mid – 1;
    }
    return mid<1 ? -1 : mid – 1;
    }
    }

    0 赞同 0 条回复
  • Thaddeus 永久会员 2024年3月15日 上午8:21

    打卡

    // 1.
        int upper(vector<int>& arr, int target) {
            int l = 0, r = arr.size() - 1;
            while(l < r) {
                int mid = l + (r - l) / 2;
                if(arr[mid] > target) r = mid;
                else l = mid + 1;
            }
            return l;
        }
        // 2.
        int upper(vector<int>& arr, int target) {
            int l = 0, r = arr.size() - 1;
            while(l < r) {
                int mid = l + (r - l) / 2;
                if(arr[mid] > target) r = mid;
                else l = mid + 1;
            }
            if(l - 1 >= 0 && arr[l - 1] == target) return l - 1
            return l;
        }
        // 3.
        int lower(vector<int>& arr, int target) {
            int l = 0, r = arr.size() - 1;
            while(l < r) {
                int mid = l + (r - l + 1) / 2;
                if(arr[mid] >= target) r = mid - 1;
                else l = mid;
            }
            return l;
        }
        // 4.
        int floor_lower(vector<int>& arr, int target) {
            int l = 0, r = arr.size() - 1;
            while(l < r) {
                int mid = l + (r - l + 1) / 2;
                if(arr[mid] >= target) r = mid - 1;
                else l = mid;
            }
            if(l + 1 < arr.size() && arr[l + 1] == target) return l + 1;
            return l;
        }
    
    0 赞同 0 条回复
  • MARS 普通 2024年3月14日 下午11:49
    let arr = [1, 2, 3, 3, 3, 4, 5, 5, 7], target = 3
    //寻找第一个大于 target 的元素的下标
    let upper = function (arr, target) {
      let left = 0, right = arr.length - 1
      if (arr[right] <= target) return -1  //处理特殊情况,最大值
      while (left < right) {  //当循环结束,l==r,当mid大于
        let mid = Math.floor((left + right) / 2)
        if (arr[mid] > target) {// 中值大于target,r太大了,缩小
          right = mid    //这里是开区间,不要设置mid-1
        } else if (arr[mid] == target) {
          left = mid + 1
        } else {
          left = mid + 1
        }
      }
      return left
    }
    // console.log(upper(arr, 3))
    
    //如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,如果不存在,则返回第一个大于 target 的元素下标
    let floor_upper = function (arr, target) {
      let left = 0, right = arr.length - 1
      if (arr[right] < target) return -1  //处理特殊情况,最大值
      while (left < right) {
        let mid = Math.floor((left + right) / 2)
        if (arr[mid] > target) {
          right = mid
        }
        else if (arr[mid] == target) {
          left = mid + 1
        } else {
          left = mid + 1
        }
      }
      if (arr[left - 1] == target && left - 1 >= 0) return left - 1  //注意left越界情况,左侧不变,右侧一直缩小
      return left
    }
    // console.log(upper(arr, 4))
    
    
    //3.寻找最后一个小于 target 的元素的下标,本案例中 2 则是最后一个小于 target 的,下标 = 1. //如果都不存在,则返回-1
    let lower = function (arr, target) {
      let left = 0, right = arr.length - 1
      if (arr[left] >= target) return -1  //处理特殊情况,最大值  【l,mid,r】
      while (left < right) {
        let mid = Math.cell((left + right) / 2)
        if (arr[mid] > target) {
          right = mid - 1
        }
        else if (arr[mid] == target) {
          right = mid - 1
        } else {
          left = mid
        }
      }
      return left
    }
    
    //4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,// 如果不存在,则返回最后一个小于 target 的元素的下标
    let floor_lower = function (arr, target) {
      let left = 0, right = arr.length - 1
      if (arr[left] > target) return -1  //处理特殊情况,最大值  【l,mid,r】
      while (left < right) {
        let mid = Math.cell((left + right) / 2)
        if (arr[mid] > target) {
          right = mid - 1
        }
        else if (arr[mid] == target) {
          right = mid - 1
        } else {
          left = mid
        }
      }
      if (arr[left + 1] == target && left+1<arr.length) {  //保证数组不越界
        return left + 1
      }
      return left
    }
    
    0 赞同 0 条回复
  • heathhou 普通 2024年3月14日 下午11:30
    #include <iostream>
    #include <array>
    #include <vector>
    
    using namespace std;
    
    // 使用【左闭右闭】
    class BanarySort {
    public:
        //1.寻找第一个大于 target 的元素的下标,案例:arr[1, 2,3,3,3,4,5,5,7], target = 3。
        static int upper(vector<int> arr, int target){
            int l = 0;
            int r = arr.size() - 1;//注意点,使用【左闭右闭】
            // 判断特殊情况: 没有大于target的元素
            if(arr[r] <= target){
                return -1;
            }
            //[l,r],,在我们二分查找的过程中,不断缩小我们的查找范围,直到范围里面只有一个元素,那个就是我们要找的元素了
            while(l < r){
                int mid = l + (r - l) / 2;
                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 的元素下标
        static int floor_upper(vector<int> arr, int target){
            int l = 0;
            int r = arr.size() - 1;//注意点,使用【左闭右闭】
            // 判断特殊情况: 没有大于等于target的元素
            if(arr[r] < target){
                return -1;
            }
    
            //[l,r],,在我们二分查找的过程中,不断缩小我们的查找范围,直到范围里面只有一个元素,那个就是我们要找的元素了
            while(l < r){
                int mid = l + (r - l) / 2;
                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 的元素的下标
        static int lower(vector<int> arr, int target){
            int l = 0;
            int r = arr.size() - 1;//注意点,使用【左闭右闭】
            // 判断特殊情况: 没有小于target的元素
            if(arr[l] >= target){
                return -1;
            }
    
            //[l,r],,在我们二分查找的过程中,不断缩小我们的查找范围,直到范围里面只有一个元素,那个就是我们要找的元素了
            while(l < r){
                int mid = l + (r - l + 1) / 2; // 使mid向上取整,防止 l=mid 导致 死循环
                if(arr[mid] > target){
                    r = mid - 1;
                }else if(arr[mid] < target){
                    l = mid;
                }else{ // arr[mid] == target
                    r = mid - 1;
                }
            }
            return l;
        }
    
        // 4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,
        // 如果不存在,则返回最后一个小于 target 的元素的下标
        static int floor_lower(vector<int> arr, int target){
            int l = 0;
            int r = arr.size() - 1;//注意点,使用【左闭右闭】
            // 判断特殊情况: 没有小于等于target的元素
            if(arr[l] > target){
                return -1;
            }
    
            //[l,r],,在我们二分查找的过程中,不断缩小我们的查找范围,直到范围里面只有一个元素,那个就是我们要找的元素了
            while(l < r){
                int mid = l + (r - l + 1) / 2; // 使mid向上取整,防止 l=mid 导致 死循环
                if(arr[mid] > target){
                    r = mid - 1;
                }else if(arr[mid] < target){
                    l = mid;
                }else{ // arr[mid] == target
                    r = mid - 1;
                }
            }
    
            if(l + 1 <= arr.size() && arr[l+1] == target){
                return l+1;
            }
            return l;
        }
    };
    
    
    int main() {
    
        vector<int> arr{1,2,3,3,3,4,5,5,7};
    
        int target = 3;
        int index = BanarySort::lower(arr, target);
        std::cout << "index = "  << index << ", value = " << arr[index] << std::endl;
    
        return 0;
    }
    
    0 赞同 0 条回复
  • 白雪公主倒拔垂杨柳 永久会员 2024年3月14日 下午10:12

    “` c++
    package BanarySort;
    import java.util.*;

    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 = upper(arr, target);
    // int index = floor_upper(arr, target);
    // int index = lower(arr, target);
    int index = floor_lower(arr, target);
    System.out.println(“index = “+ index + “, value = ” + arr[index]);
    }

    //1.寻找第一个大于 target 的元素的下标
    public static int upper(int[] arr, int target){
        int l=0;
        int r=arr.length-1;
    
        //如果都不存在,则返回-1
        if(arr[r] <= target){
            return -1;
        }
    
        while(l<r){
            int mid=l+(r-l)/2;
            if(arr[mid]<target){
                l=mid+1;
            }else if(arr[mid]>target){
                r=mid;
            }else{ //arr[mid]==target
                l=mid+1;
            }
        }
    
        return l;  // 运行到只剩最后一个
    }
    
    // 2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,如果不存在,则返回第一个大于 target 的元素下标。
    public static int floor_upper(int[] arr, int target){
        int l=0;
        int r=arr.length-1;
    
        //如果都不存在,则返回-1
        if(arr[r] < target){
            return -1;
        }
    
        while(l<r){
            int mid=l+(r-l)/2;
            if(arr[mid]<target){
                l=mid+1;
            }else if(arr[mid]>target){
                r=mid;
            }else{ //arr[mid]==target
                l=mid+1;
            }
        }
    
        if(l - 1 >= 0 && arr[l - 1] == target){
            return l -1;
        }
        return l;
    }//index = 4, value = 3
    
    //3. 寻找最后一个小于 target 的元素的下标
    public static int lower(int[] arr, int target){
        int l=0;
        int r=arr.length-1;
    
        if(arr[0] >= target){
            return -1;
        }
    
        while(l<r){
            int mid=l+(r-l+1)/2;
            if(arr[mid]<target){
                l=mid;
            }else if(arr[mid]>target){
                r=mid-1;
            }else{ //arr[mid]==target
                r=mid-1;
            }
        }
    
        return l;
    } // index=1,value=2
    
    //4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,如果不存在,则返回最后一个小于 target 的元素的下标。
    public static int floor_lower(int[] arr, int target){
        int l=0;
        int r=arr.length-1;
    
        if(arr[0] >= target){
            return -1;
        }
    
        while(l<r){
            int mid=l+(r-l+1)/2;
            if(arr[mid]<target){
                l=mid;
            }else if(arr[mid]>target){
                r=mid-1;
            }else{ //arr[mid]==target
                r=mid-1;
            }
        }
    
        if(l + 1 < arr.length && arr[l + 1] == target){
            return l + 1;
        }
    
        return l;
    
    }//index=2,value=3
    

    }

    “`

    0 赞同 0 条回复
  • 紫芝 普通 2024年3月14日 下午10:06

    代码

    “`c++
    int Upper(vector& vec, int target) {
    int len = vec.size();
    if (len == 0) return -1;
    int start=0, end=len-1, mid;
    while (start <= end) { mid = (start+end)/2; if (vec[mid] <= target) start = mid + 1; else end = mid - 1; } return start >= len ? -1 : start;
    }
    int floor_upper(vector
    & vec, int target){
    int len = vec.size();
    if (len == 0) return -1;
    int start = 0, end = len-1, mid;
    while (start <= end) { mid = (start + end) / 2; if (vec[mid] == target) break; else if (vec[mid] < target) start = mid + 1; else end = mid - 1; } if (vec[mid] == target) { while (vec[mid] == target) mid++; return mid - 1; } return start >= len ? -1 : start;
    }
    int Lower(vector
    & vec, int target) {
    int len = vec.size();
    if (len == 0 ) return -1;
    int start = 0, end = len – 1, mid;
    while (start <= end) { mid = (start + end) / 2; if (vec[mid] >= target) end = mid – 1;
    else start = mid + 1;
    }
    return start – 1;
    }
    int floor_lower(vector
    & vec, int target) {
    int len = vec.size();
    if (len == 0 ) return -1;
    int start = 0, end = len – 1, mid;
    while (start <= end) { mid = (start + end) / 2; if (vec[mid] == target) break; else if (vec[mid] > target) end = mid – 1;
    else start = mid + 1;
    }
    if (vec[mid] == target) {
    while (vec[mid] == target) mid–;
    return mid + 1;
    }
    return start – 1;
    }
    “`

    0 赞同 0 条回复
  • 进取 普通 2024年3月14日 下午9:58

    class Solution {
    public:
    int search(vector& nums, int target) {
    int low = 0,high = nums.size()-1;
    while(low<=high){
    int q = (high-low)/2 + low;
    if(nums[q]<target){
    low = q + 1;
    }
    else if(nums[q]>target){
    high = q – 1;
    }
    else{
    return q;
    }
    }二分模板进行修改。尽量二分的模板内少加逻辑判断。二分只负责找数字,外面判断即可
    return -1;
    }
    };

    0 赞同 0 条回复
  • 机电皮怪 永久会员 2024年3月14日 下午9:57

    C++
    //第一个问题
    int upper(int[] arr, int target)
    {
    int left = 0;
    int right = arr.size() – 1;
    //特殊情况
    if(target >= arr[right])
    {
    return -1;
    }
    while(left < right)
    {
    int mid = (right – left)/2 + left;
    if(target > arr[mid])
    {
    left = mid + 1;
    }
    else if(target < arr[mid])
    {
    right = mid;
    }
    else
    {
    left = mid + 1;
    }
    }
    return left;
    }

    //第二个问题
    int floor_upper(int[] arr, int target)
    {
    int left = 0;
    int right = arr.size() – 1;
    //特殊情况
    if(target > arr[right])
    {
    return -1;
    }
    while(left < right)
    {
    int mid = (right – left)/2 + left;
    if(arr[mid] > target)
    {
    right = mid;
    }
    else if(arr[mid] < target)
    {
    left = mid + 1;
    }
    else //arr[mid] = target
    {
    left = mid + 1;
    }
    }
    //判断一下前面的元素是不是最后一个大小等于target的
    if(left – 1 >= 0 && arr[left – 1] target)
    {
    return left – 1;
    }
    return left;
    }

    //第三个问题
    int lower(int[] arr, int target)
    {
    int left = 0;
    int right = arr.size() – 1;
    //特殊情况
    if(arr[0] >= target)
    {
    return -1;
    }
    while(left < right)
    {
    int mid = (right – left)/2 + left;
    if(target > arr[mid])
    {
    left = mid;
    }
    else if(target < arr[mid])
    {
    right = mid – 1;
    }
    else
    { //target mid
    right = mid – 1;
    }
    return left;
    }
    }

    //第四个问题
    int floor_lower(int[] arr, int target)
    {
    int left = 0;
    int right = arr.size() – 1;
    //特殊情况
    if(arr[0] > target)
    {
    return -1;
    }
    while(left > right)
    {
    int mid = (right – left)/2 + left;
    if(target > arr[mid])
    {
    left = mid;
    }
    else if(target < arr[mid])
    {
    right = mid – 1;
    }
    else
    { //target = arr[mid]
    right = mid – 1;
    }
    }
    //判断下一个元素是否等于target
    if(left + 1 < arr.size() && arr[left + 1] target && arr[left] != target)
    {
    return left +1;
    }
    return left;
    }

    0 赞同 0 条回复
  • mpweixin用户 普通 2024年3月14日 下午8:30

    思路:在二分模版里面修改返回的条件即可
    public static int upper(int[] arr, int target){
    int r=arr.length-1;
    int l=0;
    if(arr[r]<=target) return -1;
    while(l<r){
    int mid=(r-l)/2+l;//避免i+j溢出
    if(arr[mid]>target){
    r=mid;
    }else if(arr[mid]target){
    l=mid+1;
    }else{
    l=mid+1;
    }
    }
    return l;
    }

    0 赞同 0 条回复

# 回答此问题

后才能回答