zoukankan      html  css  js  c++  java
  • 母牛2年生小牛 5年后并死去的算法

    同事提出一个问题,关于牛生小牛的算法,之前的牛生小牛的算法都是假设牛不死的情况下的,几年生一头,若干年后还有多少头,这个算法是有些变化的。

    农场第一年有一头牛,假设这头牛每2年生一次小牛,小牛迅速长大,2年后又能生小牛,但是牛活到5岁的时候回自然的死去,那么求第N年还有多少牛。

    我想,这个问题的难点在于,牛要死去。自然而然的,这里要进行设置一个条件,当牛的年龄达到5岁,让牛死去(就是让这个元素消失)。同事基于这种思路,写出了第一版本的代码

    按照题意逻辑理解,进行顺序逻辑判断,编程代码如下

    <?php
    $fun=function($n){
        $list=[1];
        while ($n--) {
            foreach ($list as $k => $v) {
                if($v%2==0)
                {
                    $list[]=1;//生一头小牛
                }
                if($v==5)
                {
                    unset($list[$k]);//到五岁了 牛死了
                    continue;
                }
                $list[$k]++;//牛长大了一岁
            }
        }
        return count($list);//返回牛的数目
    };
    echo $fun(10);
    exit();

    这个代码逻辑非常清晰,是基础中的典范,然而,我们发现当年数增加的时候,内存会溢出,比如在求100年以后的时候

    然后他提出了改进方案使用array_pop回收

    截图如下

    代码如下:

    <?php
    $fun1 = function($n){
        $list = [1];
        while($n--){
            foreach($list as $k => $v){
                if($v%2 == 0){
                    $list[] = 1;
                }
                if($v == 5){
                    //unset($list[$k]);
                    $list[$k] = array_pop($list);
                    continue;
                }
                $list[$k]++;
            }
        }
        return count($list);
    };
    
    echo $fun1(100);
    exit();

    然而这样还是会爆出内存泄漏 而且多了一个notice

    针对牛的死去,以及再生,我通过牛的数量寻找规律想到了一个方案,不知道能不能被理解。

    截图如下:

    代码如下:

    <?php
    $sum=get_cow_num(10);
    var_dump($sum);
    exit();
    
    function get_cow_num($n)
    {
        $sum=1;
        for ($i=1; $i < $n; $i++)
        {
            $sum = $i%2!=0 ? $sum*2 : $sum-peibona($i/2-1);//奇数年要翻倍 偶数年减去斐波那契数
        }
        return $sum;
    }
    function peibona($n)
    {
        if($n<=0){return 0;}
        if($n<=2){return 1;}
        return peibona($n-1)+peibona($n-2);
    }

    在计算100年以后的时候 30秒时间不足

     

    我想办法延长时间

    结果……

     

    十分钟过去了,程序仍然没有停止的意思,真的是够够的了,看来递归不太适合,我猜测最后会因为递归,报错提示PHP不能递归超过99层,因为之前出过这样的问题。

    那么我改进一下,采用曾经解决过的斐波那算法来解决这个问题。

    这牛数量也太多了吧……

     代码如下:

    <?php
    set_time_limit(0);
    $sum=get_cow_num(100);
    var_dump($sum);
    exit();
    
    function get_cow_num($n)
    {
        $sum=1;
        for ($i=1; $i < $n; $i++)
        {
            $sum = $i%2!=0 ? $sum*2 : $sum-peibona($i/2-1);//奇数年要翻倍 偶数年减去斐波那契数
        }
        return $sum;
    }
    function peibona($n)
    {
        if($n<=0){return 0;}
        if($n<=2){return 1;}
        $array=array_fill(0,$n,0);
        $array[0]=0;
        $array[1]=1;
        $array[2]=1;
        for ($i=3; $i <= $n; $i++)
        {
            $array[$i]=$array[$i-1]+$array[$i-2];
        }
        return $array[$n];
    }

    这这段代码有没有优化的地方呢?当然有我们发现每次算斐波那切数都是要循环重置进行计算,为何不用静态缓存呢?

    代码如下:

    <?php
    set_time_limit(0);
    $sum=get_cow_num(100);
    var_dump($sum);
    exit();
    
    function get_cow_num($n)
    {
        $sum=1;
        for ($i=1; $i < $n; $i++)
        {
            $sum = $i%2!=0 ? $sum*2 : $sum-peibona($i/2-1,$n/2-1);//奇数年要翻倍 偶数年减去斐波那契数
        }
        return $sum;
    }
    function peibona($n,$total_num)
    {
        static $array;
        if(!isset($array[$n]))
        {
            if($n<=0)
            {
                $array[$n]=0;
            }elseif($n<=2)
            {
                $array[$n]=1;
            }
            else
            {
                $array=array_fill(0,$n,0);
                $array[0]=0;
                $array[1]=1;
                $array[2]=1;
                for ($i=3; $i <= $n; $i++)
                {
                    $array[$i]=$array[$i-1]+$array[$i-2];
                }
            }
        }
        return $array[$n];
    }

    这代码,哈哈哈哈,风骚的让人无法理解啊!

    后来根据同事总结规律得出公式,采用偶数翻倍,奇数减去斐波那切数的公式,得到python代码

    这代码极其风骚,采用递归完成,不过我估计不用递归应该更快才对。

    关于斐波那切数的通项公式可以参考百度百科 https://baike.baidu.com/item/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97/99145?fr=aladdin

  • 相关阅读:
    Flex 医疗行程图
    java cmd 命令
    面向对象的ExtJS场景开发
    spring Integration服务总线

    Vue.js 渲染函数, JSX(未掌握,未学完)
    JavaScript--Array; Array.prototype
    Vue.js 响应式原理
    Turbolinks
    LINQ 操作符
  • 原文地址:https://www.cnblogs.com/lizhaoyao/p/8716512.html
Copyright © 2011-2022 走看看