原文節選自《劍指offer》
題目:把
n個骰子扔在地上,所有骰子朝上一面的點數之和為
s。輸入
n,列印出
s的所有可能的值出現的概率。
分析:玩過麻將的都知道,骰子一共
6個面,每個面上都有乙個點數,對應的數字是1到
6之間的乙個數字。所以,
n個骰子的點數和的最小值為
n,最大值為
6n。因此,乙個直觀的思路就是定義乙個長度為
6n-n
的陣列,和為
s的點數出現的次數儲存到陣列第
s-n個元素裡。另外,我們還知道
n個骰子的所有點數的排列數6
^n。一旦我們統計出每一點數出現的次數之後,因此只要把每一點數出現的次數除以
n^6,就得到了對應的概率。
該思路的關鍵就是統計每一點數出現的次數。要求出
n個骰子的點數和,我們可以先把
n個骰子分為兩堆:第一堆只有乙個,另乙個有
n-1個。單獨的那乙個有可能出現從1到
6的點數。我們需要計算從1到
6的每一種點數和剩下的
n-1個骰子來計算點數和。接下來把剩下的
n-1個骰子還是分成兩堆,第一堆只有乙個,第二堆有
n-2個。我們把上一輪那個單獨骰子的點數和這一輪單獨骰子的點數相加,再和剩下的
n-2個骰子來計算點數和。分析到這裡,我們不難發現,這是一種遞迴的思路。遞迴結束的條件就是最後只剩下乙個骰子了。
基於這種思路,我們可以寫出如下**:
intg_maxvalue = 6;
void
printsumprobabilityofdices_1(int number)
delete
pprobabilities; }
void
sumprobabilityofdices(int number, int* pprobabilities)
void
sumprobabilityofdices(int original, int current, int value, int tempsum, int* pprobabilities)
else
} }上述演算法當
number
比較小的時候表現很優異。但由於該演算法基於遞迴,它有很多計算是重複的,從而導致當
number
變大時效能讓人不能接受。關於遞迴演算法的效能討論,詳見
本部落格系列的第16題
。 我們可以考慮換一種思路來解決這個問題。我們可以考慮用兩個陣列來儲存骰子點數每一總數出現的次數。在一次迴圈中,第乙個陣列中的第
n個數字表示骰子和為
n出現的次數。那麼在下一迴圈中,我們加上乙個新的骰子。那麼此時和為
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之和。基於這個思路,我們可以寫出如下**:
void
printsumprobabilityofdices_2(int number)
int flag = 0;
for (int i = 1; i <= g_maxvalue; ++i)
pprobabilities[flag][i] = 1;
for (int k = 2; k <= number; ++k)
flag = 1 - flag; }
double total = pow((double)g_maxvalue, number);
for(int i = number; i <= g_maxvalue * number; ++i)
delete pprobabilities[0];
delete pprobabilities[1]; }
值得提出來的是,上述**沒有在函式裡把乙個骰子的最大點數硬編碼
(hard code)為6
,而是用乙個變數
g_maxvalue
來表示。這樣做的好處時,如果某個廠家生產了最大點數為4或者
8的骰子,我們只需要在**中修改乙個地方,擴充套件起來很方便。如果在面試的時候我們能對面試官提起對程式擴充套件性的考慮,一定能給面試官留下乙個很好的印象。
劍指offer n個骰子的點數
思路 這裡可以用兩個陣列來儲存骰子點數的每個總數出現的次數。在一輪迴圈中,第乙個陣列中的第n個數字表示骰子的和為n出現的次數。在下一輪的迴圈中,加上乙個新的骰子,此時和為n的骰子出現的次數應該等於上一輪迴圈中骰子點數和為n 1,n 2,n 3,n 4,n 4,n 5與n 6次數的總和,所以把另外乙個...
劍指offer n個骰子的點數(java)
題目 把n個骰子仍在地上,所有骰子朝上一面的點數之和為s,輸入n,列印出s的所有可能的值出現的概率。骰子一共6個面,每個面上都有乙個點數,對應的是1 6之間的乙個數字。所以n個骰子的點數和的最小值是n,最大值為6n.另外根據排列組合的知識,我們還知道n個骰子的所有點數的排列數為6 n.要解決這個問題...
面試題60 劍指offer n個骰子的點數
題目 把n個骰子扔在地上,所有骰子朝上一面的點數之和為s。輸入n,列印出s的所有可能的值出現的概率。示例 輸入 n 2 輸出 解法 動態規劃規律 f n f n 1 f n 2 f n 3 f n 4 f n 5 f n 6 向已有的骰子中再加入乙個骰子,此時和為n出現的次數應為和為n 1,n 2,...