二分查找及其基本拓展

while(left < right) {
        long long mid = (left + right + 1) / 2;
        long long now = fun(mid);
        if(now >= m) {
            left = mid;
        } else {
            right = mid - 1;
        } 
    }

对于 left = mid, 左边界如果为 mid 了, 且下一次循环时 mid 等于 left 就会造成死循环, 所以我们需要控制mid 向上取.
至于为什么要 left = mid 是题目要求答案尽可能的高


如果数据之间的比较操作非常耗时,不管数据量大小,我都推荐使用二分查找。比如,数组中存储的都是很长的字符串,如此长的两个字符串之间比对大小,就会非常耗时。
我们需要尽可能地减少比较次数,而比较次数的减少会大大提高性能,这个时候二分查找就比顺序遍历更有优势。

查找第一个值等于给定值的元素

	// 变种一:有序数组存在重复数据,查找第一个值等于给定值的元素
int binarySearch(int *a, int n, int value) {
    if (n == 0) return -1;
    if (n == 1) return 0;
    int low = 0;
    int high = n - 1;
    while (low <= high) {
        int mid = low + ((high - low) >> 1);
        if (a[mid] < value) {
            low = mid + 1;
        } else if (a[mid] > value) {
            high = mid - 1;
        } else {
            if (mid == 0 || a[mid - 1] != value) return mid;
            high = mid - 1;
        }
    }
    return -1;
}

查找最后一个值等于给定值的元素

	// 变种二:有序数组存在重复数据,查找最后一个值等于给定值的元素
 int binarySearch(int *a, int n, int value) {
     if (n == 0) return -1;
     if (n == 1) return 0;
     int low = 0;
     int high = n - 1;
     while (low <= high) {
         int mid = low + ((high - low) >> 1);
         if (a[mid] < value) {
             low = mid + 1;
         } else if (a[mid] > value) {
             high = mid - 1;
         } else {
             if (mid == n - 1 || a[mid + 1] != value) return mid;
             low = mid + 1;
         }
     }
     return -1;
 }

查找第一个大于等于给定值的元素

	// 变种三:有序数组存在重复数据,查找第一个大于等于给定值的元素
 int binarySearch(int *a, int n, int value) {
     if (n == 0) return -1;
     if (n == 1) return 0;
     int low = 0;
     int high = n- 1;
     while (low <= high) {
         int mid = low + ((high - low) >> 1);
         if (a[mid] >= value) {
             if (mid == 0 || a[mid - 1] < value) return mid;
             high = mid - 1;
         } else {
             low = mid + 1;
         }
     }
     return -1;
 }

查找最后一个小于等于给定值的元素

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值