1. 程式人生 > >演算法-棧的出棧個數

演算法-棧的出棧個數

import java.math.BigInteger;

/**
問題描述:
	n個元素的出棧次序
	f(n)=f(0)*f(n-1)+f(1)*f(n-2)...+f(n-2)*f(1)+f(n-1)*f(0)
輸出樣例:
0:1
1:1
2:2
3:5
4:14
5:42
6:132
7:429
8:1430
9:4862
10:16796
11:58786
12:208012
13:742900
14:2674440
15:9694845
16:35357670
17:129644790
18:477638700
19:1767263190
20:6564120420

 * @author Vivinia
 */
public class StackNum {
	static BigInteger[] num=new BigInteger[101];         //使用陣列儲存之前計算過的資料
	public static void main(String[] args) {
		for(int i=0;i<=100;i++)         
			num[i]=BigInteger.valueOf(0);           //先全部賦值為0
		num[0]=BigInteger.valueOf(1);             
		for(int i=0;i<=100;i++)
			System.out.println(i+":"+f(i));
	}

	private static BigInteger f(int n) {
		BigInteger total=BigInteger.valueOf(0);
		if(n==0)
			return num[0];        //0是退出遞迴的邊界條件
		if(num[n]!=BigInteger.valueOf(0))
			return num[n];        //判斷以前是否計算過資料,如果計算過資料直接從陣列中取出,不用再次計算
		for(int i=0;i<n;i++)
			total=total.add((f(i).multiply(f(n-i-1))));   //迴圈累加每次成績
		num[n]=total;        //將該次資料儲存起來
		return total;
	}

}

需要注意的地方:

1.首先找到通用公式f(n)=f(0)*f(n-1)+f(1)*f(n-2)...+f(n-2)*f(1)+f(n-1)*f(0),嗯,我從網上查的。。。

2.核心程式碼就是遞迴中的for迴圈語句,外加退出遞迴的return 1,但是如果只這樣遞迴,在n為16時就明顯感覺時間變慢,大約接近一秒鐘,然後往後時間為指數增長,到20就已經超過人的耐心等待時間了,這是因為每次計算一個數,都把前邊的資料重新算了一遍,做了很多無用功,所以定義一個數組把每次計算的資料儲存起來,以後先查詢陣列,陣列沒有儲存再計算;

3.雖然網上搜著long型資料很大,但是如果用long到n=20時就溢位了,所以改用BigInteger型,現在測試到100輸出都沒問題,而且時間很快,只不過就是不知道資料的資料對不對,反正很大。。。