劍指Offer n個骰子扔出點數和S的概率

2021-07-11 01:16:55 字數 2232 閱讀 2306

原文節選自《劍指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,...