#數據結構與算法學習筆記#劍指Offer8:普通青蛙跳臺階+變態青蛙跳臺階+最清晰數學歸納法證明(Java、C/C++)

2018.8.3

普通青蛙跳臺階問題實際上是一道斐波那契數列的題目,可以直接參考上一篇對斐波那契數列的算法分析和實現的文章——#數據結構與算法學習筆記#劍指Offer7:斐波那契數列的四種編程實現方法 + 測試用例(Java、C/C++)

變態青蛙跳臺階問題就厲害了,思想其實本質還是斐波那契數列的思想,但是卻不需要編程循環或者遞歸模擬斐波那契的加和過程,只需要用順推的思想+數學歸納法歸納就可以確定公式  f\left ( n \right ) = 2^{n - 1}  。


普通跳青蛙題目描述

一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果)。

變態跳青蛙題目描述

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


普通跳青蛙原理:

斐波那契數列:f\left ( n \right ) = f\left ( n - 1 \right ) + f\left ( n - 2 \right ),其中,f\left ( 1 \right ) = 1f\left ( 2 \right ) = 2

思路:由後往前倒推,當青蛙站在第n級臺階時回顧上一步,他到達第n級臺階可以有兩種方式:1.從下一級臺階第n-1級往上跳1步,2.從下兩級臺階第n-2級往上跳2步。那青蛙到第n級臺階的方法數f\left ( n \right )實際上就等於先通過前兩種方式到達上一步的方法數總和f\left ( n - 1 \right ) + f\left ( n - 2 \right )

 

變態跳青蛙公式數學歸納法證明:

我們觀察有:f\left ( 1 \right ) = 1 = 2^{1 - 1}f\left ( 2 \right ) = 2 = 2^{2 - 1}f\left ( 3 \right ) = 4 = 2^{3 - 1}f\left ( 4 \right ) = 8 = 2^{4 - 1}……

於是我們猜想:f\left ( n \right ) = 2^{n - 1}

通過普通跳青蛙原理的延伸,我們可以知道(十分重要):f\left ( n \right ) = f\left ( n - 1 \right ) + f\left ( n - 2 \right )......f\left ( 2 \right ) + f\left ( 1 \right )

數學歸納法證明:

① 當n = 1 時,有f\left ( 1 \right ) = 1 = 2^{1 - 1}

② 假設當n = k時,有f\left ( k \right ) = 2^{k - 1}

\because  f\left ( n \right ) = f\left ( n - 1 \right ) + f\left ( n - 2 \right )......f\left ( 2 \right ) + f\left ( 1 \right )

\therefore  則當n = k + 1時,f\left ( k + 1 \right ) = f\left ( k \right ) + (f\left ( k - 1 \right )......f\left ( 2 \right ) + f\left ( 1 \right )) = f\left ( k \right ) + f\left ( k \right ) = 2f\left ( k \right )

\therefore  f\left ( k + 1 \right ) = 2f\left ( k \right ) = 2 * 2^{k - 1} = 2^{k}   

\therefore  f\left ( n \right ) = 2^{n - 1}得證。


普通青蛙跳臺階編程實現:其實就是求斐波那契數列,一共有四種實現方法,可以參考上一篇文章的代碼實現,#數據結構與算法學習筆記#劍指Offer7:斐波那契數列的四種編程實現方法 + 測試用例(Java、C/C++),完全一模一樣。當然我還是貼出幾種來給大家做個參考。

普通青蛙跳臺階Java實現:

/**
 * 
 * @author ChopinXBP 
 * 一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果)。
 * 
 *
 */
public class JumpFloor {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int num = Solve(5);
		int num2 = Solve2(5);
		System.out.println(num);
		System.out.println(num2);
	}

	//迭代法解答,清晰明瞭,但效率極低
	public static int Solve(int target) {
		if (target < 3)
			return target;

		return Solve(target - 1) + Solve(target - 2);
	}

	// 最佳解答:循環順推法
	public static int Solve2(int target) {

		if (target == 1 || target == 2) {
			return target;
		}

		// 第一階和第二階考慮過了,初始當前臺階爲第三階,向後迭代
		// 思路:當前臺階的跳法總數=當前臺階後退一階的臺階的跳法總數+當前臺階後退二階的臺階的跳法總數

		int jumpSum = 0;// 當前臺階的跳法總數
		int jumpSumBackStep1 = 2;// 當前臺階後退一階的臺階的跳法總數(初始值當前臺階是第3階)
		int jumpSumBackStep2 = 1;// 當前臺階後退二階的臺階的跳法總數(初始值當前臺階是第3階)

		for (int i = 3; i <= target; i++) {

			jumpSum = jumpSumBackStep1 + jumpSumBackStep2;
			jumpSumBackStep2 = jumpSumBackStep1;// 後退一階在下一次迭代變爲後退兩階
			jumpSumBackStep1 = jumpSum; // 當前臺階在下一次迭代變爲後退一階

		}

		return jumpSum;

	}
}

 

普通青蛙跳臺階C++實現參考:

class Solution {
public:
    int jumpFloor(int n) {
        int f=1,g=2;
        n--;
        while(n--)
        {
            g+=f;
            f=g-f;
        }
        return f;
    }
};

變態青蛙跳臺階編程實現,其實就一行代碼的事情。

變態青蛙跳臺階Java實現:

/**
 * 
 * @author ChopinXBP 
 * 一隻青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。
 * 
 *
 */
public class JumpFloor2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int num = Solve(5);
		System.out.println(num);
	}

	//可用數學歸納法證明,f(n) = 2 ^ (n - 1)
	public static int Solve(int target) {

		return (int)Math.pow(2, target - 1);
	}

}

變態青蛙跳臺階C++實現參考:效率超高的位運算。

class Solution {
public:
    int jumpFloorII(int number) {
       return  1<<--number;
    }
};

#Coding一小時,Copying一秒鐘。留個言點個讚唄,謝謝你#

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