[算法] 二分查找及其变种问题

终结条件为low == high
根据if (check(mid)) 条件成立,判断答案在左区间还是右区间,如果答案在左区间并且mid也可能是答案,那么就要按模板1[l, mid], [mid + 1, r]来划分;如果答案在右区间并且mid也可能是答案,那么就要按模板2[l, mid - 1], [mid, r]来划分。
注意check(mid)要能够保证将答案分在两侧,例如找最后一个小于等于target的数,如果条件写的是target <= nums[mid],那么如果判断为真,你的目标既有可能在mid的左侧,也有可能在mid的右侧,是没有划分效果的。如果取nums[mid] <= target则成立。

  1. 版本1
    最大值最小问题,第一个>=target的元素
    // 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        // 两个int相加减会溢出 中间加个长整型常量
        int mid = l + 0ll + r >> 1; 
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}
  1. 版本2
    最小值最大问题,最后一个<= target的元素
    //区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用,其更新操作是r = mid - 1或者l = mid。
    因为r更新为mid-1,如果mid仍然计算下取整,则l和r差1时大者永远取不到,会死循环,因此计算mid时需要加1。
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + 1ll + r >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

二分答案
https://www.cnblogs.com/lcosmos/p/9438705.html

https://www.cnblogs.com/luoxn28/p/5767571.html

旋转数组的二分查找
https://www.geeksforgeeks.org/the-ubiquitous-binary-search-set-1/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容