二分查找算法

147 阅读2分钟

整数二分

最初级的二分查找

function binarySearch(arr,l,r,x){
    let mid;
    while(l<=r){
        mid=(l+r)>>1;
        if(arr[mid]==x) return mid;
        else if(arr[mid]>x) r=mid-1;
        else l=mid+1;
    }
    return -1;
}

需要注意,如果二分上界超过int型数据范围的一半,left+right会超过int导致溢出,可以选择这种写法 mid=l+(r-l)>>1 JS我不清楚有没有这个问题,最好还是这样写吧。

二分查找数的范围

//左
function binarySearchLeft(arr,l,r,x){
    let mid;
    while(l<r){
        mid=(l+r)>>1;
        if(arr[mid]>=x){
            r=mid;
        }else{
            l=mid+1;
        }
    }
    return l;
}

//右
function binarySearchRight(arr,l,r,x){
    let mid;
    while(l<r){
        mid=(l+r+1)>>1;
        if(arr[mid]<=x){
            l=mid;
        }else{
            r=mid-1;
        }
    }
    return l;
}

两个都运行一遍就是左右边界 注意if中的条件不一定是 大于、小于 只要能够区分左右两个分区即可 可以改成

//左
function binarySearchLeft(arr,l,r,x){
    let mid;
    while(l<r){
        mid=(l+r)>>1;
        // check函数 true时 mid包括在 左侧
        if(check(arr[mid])){
            r=mid;
        }else{
            l=mid+1;
        }
    }
    return l;
}

//右
function binarySearchRight(arr,l,r,x){
    let mid;
    while(l<r){
        mid=(l+r+1)>>1;
        // check函数 true时 mid包括在 右侧
        if(check(arr[mid])){
            l=mid;
        }else{
            r=mid-1;
        }
    }
    return l;
}

浮点数二分算法

function bsearch(l,r){
    const double eps =1e-6; //浮点数经常取不到正好的值,需要设置精度 一般是 1e-6 /1e-5
    while(r-l>eps){
        let mid=(l+r)/2;
        if(check(mid)){
            r=mid
        }else{
            l=mid;
        }
    }
    return l;
}

浮点数不存在左右边界的情况,就正常二分就行了

例题,计算 根号2 的近似值

function f(x){
    return x*x;
}
// k=2
function calSqrt(k=2;){
    let l=k-1,r=k;
    const eps =1e-6;
    let mid;
    while(r-l>eps){
        mid=(l+r)/2;
        if(f(mid)>k){
            r=mid;
        }else{
            l=mid;
        }
    }
    return mid;
}

计算一个方程中的未知数 x

通过上一个例题,我们发现了一类问题的解法 给定一个定义在L,R上的 单调函数f(x), 求方程f(x)=0 的根 如求 根号2 => f(x)=x^2-2=0; 详细可看《算法笔记》 p132 e25a3376f5ea9e98f6eb4abe2ee29c7.jpg