用PHP实现二分法查找之递归和迭代

废话:

前段时间经历过的几个面试,考官都很喜欢问的一个问题是,请写一个二分法查找的算法。

我一听,嘿,简单,袖子一撸,操起键盘就扒拉扒拉。

写出来,考官一看,眉头凝成小山丘,说:你这代码网上扒的吧,我。。。从接触二分法查找后,都是这么写的,有什么问题?

不久前买了一本算法书,因为种种原因(C语言忘的太多了,读起来很费劲),只看了一丢丢就没再继续。

今天不小心知道了迭代算法。写出来的程序跑一跑的确比递归快得多。虽然不知道这个是否符合当时考官的思路,但是至少摆脱了脑海中只有递归实现二分法查找的思维定式。


关于递归和迭代分别的时间复杂度,递归的时间复杂度是O(N),而迭代的时间复杂度是O(logN),由y=N 和Y=logN两条曲线我们知道,一定是O(logN)更优一些。

以下是两段代码,和傻瓜式测效率的代码。


<?php

function dichotomyIterationSearch($arr, $n, $v)
{
    $left   = 0;
    $right  = $n - 1;
    while ($left <= $right) {
        $middle  = bcdiv(bcadd($right, $left), 2);
        if ($arr[$middle] > $v) {
            $right = $middle - 1;
        } elseif ($arr[$middle] < $v) {
            $left  = $middle + 1;
        } else {
            return $middle;
        }
    }
    return -1;
}


$arr = [];
for ($i=0;$i<300000;$i++){
    $arr[] = $i;
}
list($first) = explode(" ",microtime());
echo dichotomyIterationSearch($arr,count($arr),35387);echo '<br>';
list($second) = explode(" ",microtime());
echo round($second - $first,5)*1000000;


function dichotomyRecursionSearch($arr, $low, $high, $v)
{
    $middle = bcdiv(bcadd($low, $high), 2);

    if ($low < $high) {
        if ($arr[$middle] > $v) {
            $high = $middle - 1;
            return dichotomyRecursionSearch($arr, $low, $high, $v);
        } elseif ($arr[$middle] < $v) {
            $low = $middle + 1;
            return dichotomyRecursionSearch($arr, $low, $high, $v);
        } else {
            return $middle;
        }
    } elseif ($high == $low) {
        if ($arr[$middle] == $v) {
            return $middle;
        } else {
            return -1;
        }
    }
    return -1;
}


$arr = [];
for ($i=0;$i<300000;$i++){
    $arr[] = $i;
}
echo "<br>";
list($first) = explode(" ",microtime());
echo dichotomyRecursionSearch($arr,0, count($arr),35387);echo '<br>';
list($second) = explode(" ",microtime());
echo round($second - $first, 5)*1000000;

等等,还有一个尾递归的概念,待我研究明白,回来写博客~



如果上面代码或文字描述中又不正确的地方,请来访者能亲切的提出来,感谢~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值