二分查找算法解析

二分查找的思想很简单,但具体使用时如何快速准确套用"公式"解决二分查找类型的问题呢?

首先考虑最简单的情况,假如有一个由False和True组成的序列:

[True True True True True True False False False]

如何快速用二分查找找到第一个False?方法如下:

int low = 0;
int high = 8;//数组维度下标
while(low < high)
{
    int mid = (low + high)/2;
    if(array[mid] == True)
    {
        low = mid + 1;
    }
    else
    {
        high = mid;
    }
}

或者这样的序列,需要找到第一个True,解法类似:

[False False False False False False True True True]

int low = 0;
int high = 8;//数组维度下标
while(low < high)
{
    int mid = (low + high)/2;
    if(array[mid] == False)
    {
        low = mid + 1;
    }
    else
    {
        high = mid;
    }
}

那么不管对于什么类型的问题,我们只需要构造出这样的序列,再套用如上模式就可以解决问题。

举个例子:求正整数x的平方根,保留平方根整数部分。

0 -> 0 //大于等于0的平方,小于1的平方
1、2、3 -> 1 //大于等于1的平方,小于2的平方
4、5、6、7 -> 2//大于等于2的平方,小于3的平方

根据以上事实,我们需要找到整数x第一个小于的整数y的平方,那么将(y-1)就是解。

我们只考虑较简单的情况,假设x的平方根在0-1000范围内。

int low = 0;
int high = 1000;
while(low < high)
{
    int mid = (low + high)/2;
    if(condition(mid,x))
    {
        low = mid + 1;
    }
    else
    {
        high = mid;
    }
}

公式套用就是这样,但我们需要构造出condition(mid,x)条件来。

假设x=14,如果将条件设为x >= n*n,那么形成如下序列:
[x>=0*0 x>=1*1 x>=2*2 x>=3*3 x>=4*4] ->
[x>=0 x>=1 x>=4 x>=9 x>=16] ->
[True True True True False] ->

也就是说condition(mid,x)设为 x >= mid*mid之后,找满足条件序列的第一个False

带入上述模式最终代码如下:

int low = 0;
int high = 1000;
while(low < high)
{
    int mid = (low + high)/2;
    if( (x >= mid * mid) == True)//condition(mid,x), == True只是为了与模式代码统一
    {
        low = mid + 1;
    }
    else
    {
        high = mid;
    }
}

我们也可以构造不同的条件:

假设x=14,如果将条件设为x < n*n,那么形成如下序列:
[x<0*0 x<1*1 x<2*2 x<3*3 x<4*4] ->
[x<0 x<1 x<4 x<9 x<16] ->
[False False False False True] ->

套用后代码如下:

int low = 0;
int high = 1000;
while(low < high)
{
    int mid = (low + high)/2;
    if( (x < mid * mid) == False)//condition(mid,x) == False只是为了与模式代码统一
    {
        low = mid + 1;
    }
    else
    {
        high = mid;
    }
}

其他情况大致也可以套用如上框架。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值