1. 程式人生 > >劍指offer--變態跳臺階

劍指offer--變態跳臺階

題目如下:

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

解題思路:
其實有兩種解題思路,個人更傾向於第二種方法,應為個人覺得它更符合計算機解決問題的思路。

在這道題目之前,其實還有一個簡單的青蛙跳臺階,就是青蛙可以跳一次和跳兩次,這個其實很簡單也沒啥好說的,使用遞迴就可以得到我們想要的結果。
我們看看這道題,我一開始的想法也是使用遞迴,最後發現其實還是那麼回事。。。

思路一:

假設  青蛙跳到n級的方法是 F(n)
那麼F(n)是怎麼來的呢?我們從後往前思考
	 1.青蛙跳到第n-1級,最後跳1步 ,而跳到n-1級的跳法是F(n-1)   A1 =  F(n-1)
	 2.青蛙跳到第n-2級,最後跳2步 ,而跳到n-2級的跳法是F(n-2)   A2 =  F(n-2)
		.....
	 n-1.青蛙跳到第1級,最後跳n-1步 ,而跳到1級的跳法是F(1)   An-1 =  F(1)
	 n. 青蛙直接跳n級,An =  1

那麼我麼可以得到如下結果:
a. F(n) = A1 + A2 + …+ An-1 + An = F(n-1) + F(n-2) + … + F(1) + 1
b. F(n-1) = F(n-2) + … + F(1) + 1
c. F(n) = F(n-1) + F(n-1) = 2F(n-1)

所以結果就很簡單了

function jumpFloorII(number)
{
    if( number === 1){
        return 1;
    }else{
        return  2 * jumpFloorII(number  - 1);
    }
}

所以這道題究竟是演算法呢還是數學呢?。。。。

思路二:
這個方法是我檢視其他解法時發現的,本質和思路一差不多,不同的地方在於它並沒有上文中的推理步驟b和c,僅僅是依靠公式a就得到的最終的結果,下面讓我們一起看看程式碼

	function jumpFloorII(number)
	{
	    if(number === 1){
	        return 1;        
	    }else if( number > 1){
	        //建立一個空陣列,用來儲存對應每一個小於number的n的跳法結果        
	        let arr = new Array(number + 1).fill(0);        
	        arr[0] = 0;
	        arr[1] = 1;
	        for(let i = 2; i <= number; i++ ){
	            // An = An-1 + An-2 + ... + A1 + 1
	            for( let j = 1 ; j < i ; j++  ){
	                arr[i] += arr[j];
	            }
	            arr[i] += 1;
	        }
	        return arr[number];
	    }else{
	        return -1;
	    }
	}

巧妙的使用陣列,將每一次的An-1計算結果儲存起來,而後面的An的計算結果是依賴前面的A1…An-1的。