爬臺階問題(遞迴和動態規劃實現)

Allen-Liu發表於2017-10-06

問題描述: 一個人爬樓梯,每次只能爬1個或2個臺階,假設有n個臺階,那麼這個人有多少種不同的爬樓梯方法? 

這個問題可以分解成兩個子問題(當n>=2時),最後一步是爬1個臺階還是爬兩個臺階(兩種情況),當爬1個臺階的時候:問題就分解成,最後爬一個臺階,前面n-1個臺階有 多少種爬法?當最後爬2個臺階的時候,前面n-2個臺階有多少種爬法?然後兩個子問題方法相加就是會後結果。兩個子問題又可以再分割成更小的子問題。。。最後的結果是 到n==1這種基礎情況。(符合遞迴的條件),下面給出遞迴和動態規劃的java程式碼:

import java.util.Scanner;
public class ClimbStairs
{
	/**
	 * 使用樸素遞迴的方法和動態規劃的方法實現求爬樓梯的方法數
	 */
	public static void main(String[] args)
	{
		long start1, start2;//用於記錄兩個子函式開始執行的時間
		Scanner str = new Scanner(System.in);
		int number = str.nextInt();//獲得臺階數目
		long count[] = new long[number + 1];//用於記錄動態規劃中子問題的解
		count[0] = 1L;
		count[1] = 1L;
		start1 = System.currentTimeMillis();//記錄函式1的開始時間
		System.out.println("There are " + fun1(number) + " methods.");
		System.out.println("Cost " + (System.currentTimeMillis() - start1) + " ms.");//獲得函式1的執行時間
		start2 = System.currentTimeMillis();//記錄函式2的開始時間
		System.out.println("There are " + fun2(count, number) + " methods.");
		System.out.println("Cost " + (System.currentTimeMillis() - start2) + " ms.");//獲得函式2的執行時間
	}
	//定義樸素遞迴呼叫方法
	public static long fun1(int num)
	{
		if (num == 1)//基礎情況
			return 1L;
		else if (num == 2)//基礎情況
			return 2L;
		else
			return fun1(num - 1) + fun1(num - 2);//遞迴呼叫
	}
	//定義動態規劃方法
	public static long fun2(long count[], int num)
	{
		if (num == 1)//基礎情況
			return 1L;
		else 
		{
			for  (int i = 2; i <= num; i++)
			{
				count[i] = count[i - 1] + count[i - 2];//這裡並沒有呼叫原函式計算,而是直接使用子問題的結果
			}
		}	
		return count[num];
	}
}
There are 1836311903 methods.
Cost 4848 ms.
There are 1836311903 methods.
Cost 1 ms.
上面的結果也證實了動態規劃的效率要遠遠高於樸素遞迴的方法(這種方法不記錄前面的計算結果,每次用到的時候都重新計算)。

相關文章