二分查找汇总(转载,加了些许注释)


相关问题:

LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置

1.基本二分查找

    //1.1二分查找原始版--查找某个数的下标(任意一个)
    //在有序数组中查找某个数,找到返回数的下标,存在多个返回任意一个即可,没有返回-1。
    //所有程序采用左右均为闭区间,即函数中n为最后一个元素下标,而不是元素个数。典型代码如下:
    public int binarySearch(int[] a, int n, int key){
        //n + 1 个数
        int low = 0;
        int high = n;
        int mid = 0;
        while(low <= high) {
            mid = low + ((high-low) >> 1);
            if(key == a[mid]) {
                return mid;
            } else if(key < a[mid]) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return -1;
    }

    //1.2查找第一个大于等于某个数的下标
    //例:int[] a = {1,2,2,2,4,8,10},查找2,返回第一个2的下标1;查找3,返回4的下标4;查找4,
    //返回4的下标4。如果没有大于等于key的元素,返回-1。
    //下面是代码,改动只有两处:
//    解释:
//        1、条件为key<=a[mid],意思是key小于等于中间值,则往左半区域查找。如在 {1,2,2,2,4,8,10}查找2,第一步,low=0, high=6, 得mid=3, key <= a[3],往下标{1,2,2}中继续查找。
//        2、终止前一步为: low=high,得mid = low,此时如果key <= a[mid],则high会改变,而low指向当前元素,即为满足要求的元素。如果key > a[mid],则low会改变,而low指向mid下一个元素。
//        3、如果key大于数组最后一个元素,low最后变为n+1,即没有元素大于key,需要返回 -1。
    public int firstGreatOrEqual(int[] a, int n, int key){
        //n + 1 个数
        int low = 0;
        int high = n;
        int mid = 0;
        while(low <= high) {
            mid = low + ((high-low) >> 1);
            if(key <= a[mid]) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return low <= n ? low : -1;
    }

    //1.3查找第一个大于某个数的下标
    //例:int[] a = {1,2,2,2,4,8,10},查找2,返回4的下标4;查找3,返回4的下标4;查找4,
    //返回8的下标5。如果没有大于key的元素,返回-1。
    //如下是代码,与上面大于等于某个数仅判断一个符号不同:
    public int firstGreat(int[] a, int n, int key){
        //n + 1 个数
        int low = 0;
        int high = n;
        int mid = 0;
        while(low <= high) {
            mid = low + ((high-low) >> 1);
            if(key < a[mid]) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return low <= n ? low : -1;
    }

2.基于基本二分查找的变形

    //2.1查找数组中某个数的位置的最小下标,没有返回-1
    //直接用上面1.2,但需要处理一下,即当返回的low位置不等于key时,也返回-1(数组不含这个key)。如下:
    public int firstIndex(int[] a, int n, int key){
        //n + 1 个数
        int low = 0;
        int high = n;
        int mid = 0;
        while(low <= high) {
            mid = low + ((high-low) >> 1);
            if(key <= a[mid]) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return (low <= n) && (a[low] == key) ? low : -1;
    }

    //2.2查找数组中某个数的位置的最大下标,没有返回-1
    //直接用上面1.3,得到的下标 - 1即可,但也需要处理一下,即不用判断low <= n,
    //而是判断low-1>=0,且返回的low-1位置等于key时,才返回位置low - 1。如下:
    //(1.3得到第一个大于key的数的坐标,此坐标-1就得到了等于key的最后一个坐标)
    public int lastIndex(int[] a, int n, int key){
        //n + 1 个数
        int low = 0;
        int high = n;
        int mid = 0;
        while(low <= high) {
            mid = low + ((high-low) >> 1);
            if(key < a[mid]) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return (low - 1 >= 0 && (a[low - 1] == key))? low - 1: -1;
    }

    //2.3查找数组中小于某个数的最大下标,没有返回-1
    //直接用上面1.2,返回的low-1位置即为可能的位置。也需要处理一下,需要low-1>=0。
    public int firstLess(int[] a, int n, int key) {
        // n + 1 个数
        int low = 0;
        int high = n;
        int mid = 0;
        while (low <= high) {
            mid = low + ((high - low) >> 1);
            if (key <= a[mid]) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return (low - 1 >= 0) ? low - 1 : -1;
    }

    //2.4 查找数组中某个数的出现次数
    //使用1.2,1.3,分别求得下界first和上界last,两个相减即(last - first)是key出现次数。如下:
    public int getCount(int[] a, int n, int key) {
        // n + 1 个数
        int first = firstGreatOrEqual2(a, n, key);
        int last = firstGreat2(a, n, key);
        return last - first;
    }

    public int firstGreatOrEqual2(int[] a, int n, int key) {
        // n + 1 个数
        int low = 0;
        int high = n;
        int mid = 0;
        while (low <= high) {
            mid = low + ((high - low) >> 1);
            if (key <= a[mid]) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return low;
    }

    public int firstGreat2(int[] a, int n, int key) {
        // n + 1 个数
        int low = 0;
        int high = n;
        int mid = 0;
        while (low <= high) {
            mid = low + ((high - low) >> 1);
            if (key < a[mid]) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return low;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值