python算法之二分查找

说明:大部分代码是在网上找到的,好几个代码思路总结出来的

通常写算法,习惯用C语言写,显得思路清晰,但是如果一旦把思路确定下来,而且又不想打草稿,想快速写下来看看效果,还是python写的比较快,也看个人爱好,实习的时候有个同事对于python的缩进来控制代码块各种喷。。。。他觉得还是用大括号合适。。。怎么说呢,适合自己的才是最好的。我个人的毛病就是,写了几天C,到要转到python的时候,代码中依然有C的影子。。比如大括号问题,比如忘记在while或这for、if、else等后面加“:”,而如果写了几天Python,要转到C的时候,会忘记声明一些变量,直接拿来就用,运行的时候,各种变量未定义。在这里给自己提个醒,多思考也要多动手。

今天无意中看到了二分查找,本来以为很简单的代码,几行就结束了,后来看到了一个比较牛的代码,才发现人比人该死是永恒的真理,为了不该死,也要把不该死的代码学会才行啊,二分查找的原理很简单,就是在一个有序序列中,查找代码是一半一半的比较而不是一个一个的比较

最简单的二分查找非递归代码如下:

int search(int array[], int n, int v)
{
    int left, right, middle;

    left = 0, right = n - 1;

    while (left <= right)
    {
        middle = (left + right) / 2;
        if (array[middle] > v)
        {
            right = middle;
        }
        else if (array[middle] < v)
        {
            left = middle;
        }
        else
        {
            return middle;
        }
    }

    return -1;
}

输入:array数组,array大小n,查找元素v

输出:v的所在位置,没有找到返回-1

#####################################################################################################################################

下面写个递归的代码:

#include<stdio.h>

int search(int arr[],int low,int high,int key)
{
        int mid = (low+high)/2;
        if(low > high)
                return -1;
        if(arr[mid] == key)
                return mid;
        else if(arr[mid]>key)
                return search(arr,low,mid-1,key);
        else
                return search(arr,mid+1,high,key);
}
int main()
{
        int arr[101] = {1,2,3,4,87,90,100};
        int low = 0,high = 8,key = 87,ret;
        ret = search(arr,low,high,key);
        if(ret != -1)
                printf("the return is %d",ret);
        else
                printf("FBI warning:the return is -1,not find the key");
}

不知道递归的同学,请参考递归的吐槽。。。如图:当年第一次听到老师说递归的时候,想的就是这个


但是其实递归是这样的


好了不扯了,二分查找这个代码其实仔细看的话还是有点问题的,比如说这个三次判断,两次比较,还有就是

在循环体内,计算中间位置的时候,使用的是这个表达式:

mid = (left + right) / 2;

假如,left与right之和超过了所在类型的表示范围的话,那么middle就不会得到正确的值.
所以,更稳妥的做法应该是这样的:
mid = left + (right - left) / 2;
那我们优化一下,python代码如下:

def search(arr,n,v):
        left = -1
        right = n
        while(left+1 != right):
                mid = left+(right-left)/2
                if(arr[mid] < v):
                        left = mid
                else:
                        right = mid
        if(right >= n or arr[right] != v):
                right = -1
        return right
if __name__ == '__main__':
        arr = [1,2,4,23,87,90,555,1222,1444]
        n = len(arr)
        ret = search(arr,n,87)
        print ret

看C的代码:

int search(int array[], int n, int v)
{
    int left, right, mid;

    left = -1, right = n;

    while (left + 1 != right)
    {
        mid = left + (right - left) / 2;

        if (array[mid] < v)
        {
            left = mid;
        }
        else
        {
            right = mid;
        }
    }

    if (right >= n || array[right] != v)
    {
        right = -1;
    }

    return right;
}


这个代码先不说理不理解,光返回值只用right这个就很牛逼,这样看着很简单,但是很精髓的感觉有没有?再看while的判断,left+1!=right是不是很正点?自己理解ba



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值