zoukankan      html  css  js  c++  java
  • 你真的会二分查找吗

    二分查找经常写挂,最常写挂的就是陷入一个死循环,如何避免呢?

    网上有很多版本的二分代码。循环条件有:l < r的,有l+1 < r的,有l <= r的。做个总结吧。

    一、首先是二分查找一个值,找到返回其下标,否则返回-1。

    //在a[l] ~ a[r]中查找s
    int binary_search(int l, int r, int s){
        while(l <= r){
            int m = (l+r)/2;
            if(a[m] == s) return m;
            if(a[m] < s) l = m+1;
            else r = m-1;
        }
        return -1;
    }

    二、查找边界值

    有序数组中找到“正好大于(小于)目标数”的那个数。

    如果找不到怎么办呢?要返回什么值?

    我们这里规定,如果找大于(等于)某个值的数找不到,返回最后一个值的下一个坐标;

    //a[l] ~ a[r-1]中查找,如果不存在,则返回坐标r
    int binary_search(int l, int r, int s){
        while(l < r){
            int m = l+(r-l)/2;
            if(a[m] > s) r = m;
            else l = m+1;
        }
        return l;
    }

    如果找小于(等于)某个值的数找不到,返回第一个值的前一个坐标。

    //a[l+1] ~ a[r]中查找,如果不存在,则返回坐标l
    int binary_search(int l, int r, int s){
        while(l < r){
            int m = l+(r-l+1)/2;
            if(a[m] < s) l = m;
            else r = m-1;
        }
        return l;
    }

    总结一下,[l, r]就是所有可能的返回情况。还有就是注意m的取值,用+1调节偏左还是偏右,避免死循环。

    为什么不用(l+r)/2呢....因为l+r是负数的时候他偏左或偏右和正数的时候就不一样了;还有一点就是防l+r溢出。

    最后附一份整数三分的代码:

    在[l, r]里三分,
    取m1 = (2*l+r)/3, m2 = (l+2*r+2)/3
    如果f(m1)更优就r = m2-1,
    否则l = m1+1

    不会死循环也无需特判

    诸神对凡人心生艳羡,厌倦天堂。
  • 相关阅读:
    (原创)分享一下最近搞的tiny210V2从nand启动支持(K9GAG08U0F).
    (转)uboot 与系统内核中 MTD分区的关系
    (转)mkimage制作linux内核映像 即uImage是怎么制作的
    ExtJs 一些属性备忘录
    CSS 元素选择器
    为什么匿名内部类参数必须为final类型
    Unbuntu 14.04 64位 搭建交叉编译环境
    eclipse调试运行
    Linux中cat命令的用法
    android之json
  • 原文地址:https://www.cnblogs.com/dirge/p/5418229.html
Copyright © 2011-2022 走看看