骰子點數之和問題

6骰子之和的概率

小夥伴前陣子面試被問到一個問題:

同時擲出六個骰子,求可能出現的點數之和的概率。

思索

6個骰子,點數都是1~6,可能出現的點數和是6~36,那麼各個點數和的概率呢?

從獨立概率入手可能可以更好地解決問題,因爲不需要單獨考慮每個點數和的概率。6個骰子,每個骰子出現1、2、3、4、5、6的概率相等且獨立隨機的,所以總的情況有6^6 種(如果有10個骰子,那就是6^10種)。然後我們對這 6^6 種情況遍歷,然後根據其點數之和丟進其點數和對應的桶裏(需要6~36的31個桶)。最後,每個桶裏的情況個數/6^6即其出現的概率。

這是一種不錯的思路,如果從點數之和入手那很可能陷入很複雜的計算,因爲點數6只有1種,點數7則可能有6種,點數8點數9呢?其複雜度會隨着點數往中間挪而驟增。而且如果骰子不是6顆而是100顆呢?

代碼實現

從思索的結論看,其實我們代碼要做的就只是一個遍歷而已。

那麼,如何遍歷這6^n 種情況?6^n 表示n顆骰子出現的情況,其無非就是第n顆骰子出現的6種情況與n-1顆骰子出現的6^(n-1) 種情況的匹配。所以我們需要考慮遞歸,讓6^n 變成6^(n-1) ... 直到6^0 。

因此,該方法的構建應該是這樣的:

    public static void getDiceSum(
            int oldSum,
            int remainDiceCount,
            Map<Integer, Integer> sumMap) {
    }

oldSum用於記錄前面骰子的和,remainDiceCount表示還有多少顆骰子沒有加入計算,sumMap用於存儲最後每種和出現的次數。

最終的Java代碼如下:

    public static void getDiceSum(
            int oldSum,
            int remainDiceCount,
            Map<Integer, Integer> sumMap) {
        if (remainDiceCount == 0)
            return;
        for (int num = 1; num <= 6; num++) {
            if (remainDiceCount == 1) {
                int key = oldSum + num;
                Integer oldValue = sumMap.get(key);
                if (oldValue == null)
                    oldValue = 0;
                sumMap.put(oldSum + num, ++oldValue);
            } else {
                getDiceSum(oldSum + num, remainDiceCount - 1, sumMap);
            }
        }
    }

實際上,這是一個flatmap的過程,從1個getDiceSum映射到6個getDiceSum,再映射到36個getDiceSum...當remainDiceCount==1的時候說明可以求和了,這時再將當前的這條(6^n 中的一條)的和次數加一丟進sumMap中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章