斐波拉契數列、漢諾塔,青蛙跳臺階


 斐波拉契數列、漢諾塔,青蛙跳臺階  的算法實現

一.斐波那契數列 (1,1,2,3,5,8,13,21,34 ......)


f(n)=0,1,f(n1)+f(n2),n=0n=1n>2



  1. 遞歸解法(效率很低)
public function Fibonacci1($n)
{
  if($n <= 0){ return 0;}
  if($n == 1){ return 1; }
  return Fibonacci1($n - 1) + Fibonacci1($n - 2);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2 循環解法:改進的算法:從下往上計算。首先根據f(0)和f(1)算出f(2),再根據f(1)和f(2)算出f(3)。。。。。依此類推就可以算出第n項了。很容易理解,這種思路的時間複雜度是o(n)。實現代碼如下:

public function Fibonacci($n)
{
    int $result[2] = {0 , 1};
    if($n < 2)
        return $result[$n];

    $one= 1;
    $tow= 0;
    for($i = 2 ; $i <= $n ; ++$i)
    {
        $fibN = $one+ $tow;

        $tow= $one;
        $one= $fibN;
    }

    return $fibN;
}
二.漢諾塔
簡單的用php實現了漢諾塔問題的求解,使用遞歸調用,但是用php實現要是盤子的個數很多的話,運行起來會很慢的...
  漢諾塔主要是有三個塔座X,Y,Z,要求將三個大小不同,依小到大編號爲1,2.....n的圓盤從A移動到塔座Z上,要求
  (1):每次只能移動一個圓盤
  (2):圓盤可以插到X,Y,Z中任一塔座上
  (3):任何時候不能將一個較大的圓盤壓在較小的圓盤之上
  主要是運用了遞歸的思想,這裏使用php做個簡單的實現......
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
 
function hanoi($n,$x,$y,$z){
 
    if($n==1){
 
        move($x,1,$z);
 
    }else{
 
        hanoi($n-1,$x,$z,$y);
 
        move($x,$n,$z);
 
        hanoi($n-1,$y,$x,$z);
 
    }
 
}
 
function move($x,$n,$z){
 
    echo'movedisk'.$n.'from'.$x.'to'.$z.'<br>';
 
}
 
hanoi(10,'x','y','z');
 
?>

三.青蛙跳
一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法。

與斐波那契數列不同的是,其初始值定義稍有不同, 
當n=1時,只能跳一級臺階,一種跳法 
當n=2時,一次跳一級或兩級,兩種跳法 
所以,關於青蛙跳臺階的定義如下:

假設n級臺階是f(n)的一個函數 ,當n = 1時候只有一種跳法,n=2時候 可以一次跳1臺階 ,也可以一次跳兩個臺階 有兩種跳法,但是當n>2時,第一次跳有兩種不同的選擇,選擇跳一個臺階,那麼就剩餘f(n-1)種選擇,如果第一次跳2臺階 接下來有f(n-2)種選擇跳臺階,所以n級臺階的不同跳法f(n)=f(n-)+f(n-2)




f(n)=1,2,f(n1)+f(n2),n=1n=2n>2




  1. 非遞歸寫法(借鑑)
long long FrogJump12Step(int n)
{
    if (n <= 0)
    {
        std::cerr << "param error" << std::endl;
        return -1;
    }

    if (n == 1)
        return 1;
    if (n == 2)
        return 2;
    int frogNMinusOne = 2;//f(n-1)=2
    int frogNMinusTwo = 1;//f(n-2)=1
    int frogN = 0;
    for (unsigned int i = 3; i <= n;++i)
    {
        frogN = frogNMinusOne + frogNMinusTwo;
        frogNMinusTwo = frogNMinusOne;
        frogNMinusOne = frogN;
    }
    return frogN;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  1. 遞歸解法(借鑑)
long long FrogJump12StepRecursive(int n)
{
    if (n <= 0)
    {
        std::cerr << "param error" << std::endl;
        return -1;
    }
    if (n == 1)
        return 1;
    if (n == 2)
        return 2;
    return FrogJump12StepRecursive(n - 1) + FrogJump12StepRecursive(n - 2);
}

四.青蛙跳升級版:
一隻青蛙一次可以跳上1級臺階,也可以跳上2級......它也可以跳上n級,此時該青蛙跳上一個n級的臺階總共有多少種跳法?
按照上面的推理:

n = 1 時, 只有一種跳法  f(n) = 1;
n = 2 時 ,  有兩種跳法,第一次跳一個臺階 ,第一次跳2臺階f(2) =  f(1) + f(0) = 2;
n = 3 時,f(n)= 3;第一次跳1個臺階,就剩餘f(3-1) 跳法,第一次跳二臺階,就剩餘f(3-2) ,第一次跳出3臺階,後面還有f(3-3) ,f(3) = f(2)+f(1)+f(0) = 4
......
n = n ,第一次共有n種跳法,第一次跳1臺階,後面還有f(n-1),第一次跳2,後面還有f(n-2),第一次跳3 ,後面還有f(n-3),。。。。。。,第一次跳n臺階,後面還有f(n-n)
    f(n) = f(n-1) + f(n-2) + f(n-3) + f(n-4) + ......+f(n-n);
 因爲
  f(n-1) = f(n-2) + f(n-3) + f(n-4) + ......+f(n-n);
  => f(n) -f(n-1) = f(n-1)
 => f(n) = 2f(n-1)  n>2

f(n)=1,2,2f(n1),n=1n=2n>2

所以:f(n)=2f(n1)=22(n2)....=2n1f(0)=2n1


  1. 非遞歸解法:
public function FrogJump12nStep($n)
{
    if ($n <= 0)
    {
        return -1;
    }
    else if (n == 1)
        return 1;
    else
    {
        $fn1 = 1;
        $fn = 0;
        for ($i = 2; $i <= $n;++$i)
        {
            $fn = 2 * $fn1;
            $fn1 = $fn;
        }
        return $fn;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  1. 遞歸解法
public function  FrogJump12nStepRecursive($n)
{
    if ($n <= 0)
    {
        return -1;
    }
    else if ($n == 1)
        return 1;
    else if ($n == 2)
        return 2;
    else
        return 2 * FrogJump12nStepRecursive($n - 1);
}

     
 






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章