1. 程式人生 > 其它 >43. n 個骰子的點數及出現的概率

43. n 個骰子的點數及出現的概率

技術標籤:劍指offer--JAVA實現

題目描述:把n 個骰子扔在地上,所有骰子朝上一面的點數之和為s,輸入n,列印
出s 的所有可能出現的概率

思路:遞迴一般是自頂向下的分析求解,而迴圈則是自底向上,佔用更少的空間
和更少的時間,效能較好。定義一個二維陣列,第一次擲骰子有 6 種可能,第一
個骰子投完的結果存到 probabilities[0];第二次開始擲骰子,在下一迴圈中,我們
加上一個新骰子,此時和為 n 的骰子出現次數應該等於上一次迴圈中骰子點數和
為 n-1,n-2,n-3, n-4,n-5,n-6 的次數總和,所以我們把另一個數組的第 n 個數字設
為前一個數組對應 n-1,n-2,n-3,n-4,n-5,n-6 之和。

程式碼實現:


public Map<Integer, Double> printProbability(int number) {
	Map<Integer, Double> probabilityMap = new HashMap<>();
	if (number < 1) {
		return probabilityMap;
	}
	int g_maxValue = 6;
	int[][] probabilities = new int[2][];
	probabilities[0] = new int[g_maxValue * number + 1];
	probabilities[1] = new int[g_maxValue * number + 1];
	int flag = 0;
	// 當第一次拋擲骰子時,有 6 種可能,每種可能出現一次
	// 第一個骰子投完的結果存到了 probabilities[0]
	for (int i = 1; i <= g_maxValue; i++) {
		probabilities[0][i] = 1;
	}
	//從第二次開始擲骰子,假設第一個陣列中的第 n 個數字表示骰子和為 n 出現的次數,
	for (int k = 2; k <= number; ++k) {
		// 第 k 次擲骰子,和最小為 k,小於 k 的情況是不可能發生的,令不可能發生的次數設定為 0!
		for (int i = 0; i < k; ++i) {
			probabilities[1 - flag][i] = 0;
		}
		// 第 k 次擲骰子,和最小為 k,最大為 g_maxValue*k
		for (int i = k; i <= g_maxValue * k; ++i) {
		// 初始化,因為這個陣列要重複使用,上一次的值要清 0
			probabilities[1 - flag][i] = 0;
		    for (int j = 1; j <= i && j <= g_maxValue; ++j) {
			    probabilities[1 - flag][i] += probabilities[flag][i - j];
		    }
		}	
		// 若 flag=0,1-flag 用的就是陣列 1,而 flag=1,1-flag 用的就是陣列 0
		flag = 1 - flag;
	}

	double total = Math.pow(g_maxValue, number);
	for (int sum = number; sum <= g_maxValue * number; sum++) {
		double ratio = (double) probabilities[flag][sum] / total;
		probabilityMap.put(sum, ratio);
	}
	return probabilityMap;
}