面试题60. n个骰子的点数

https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof/

这个是剑指offer的题目。我他吗一拿到手直接把概率放到dp数组中了,导致算的时候要有很多的地方去思考,最后勉勉强强写了个大概的代码结果算n=2的时候还有部分数据是错的,我醉了。

后来看了题解区的解析我才有点理清了思路。

class Solution {
    public double[] twoSum(int n) {
        int[][] dp = new int[n+1][n*6+1];
        for(int i = 1; i <= 6;i++){
            dp[1][i] = 1;
        }
        for(int i = 2; i <= n; i++){
            for(int j = i; j <= i*6; j++){
                for(int k = 1; k <= 6; k++){
                    if(j-k<i-1){
                        break;
                    }
                    dp[i][j] += dp[i-1][j-k];
                }
            }
        }
        double total = Math.pow((double)6,(double)n);
        double[] res = new double[5*n+1];
        for (int i = n;i <= 6*n; i++){
            res[i-n] = ((double)dp[n][i])/total;
        }
        return res;
    }
}

这个思路是先统计n个骰子的时候,数值为i出现的组合数,然后因为总的组合数我们是已知的,我们可以直接拿组合数/总数得到具体的概率。

首先是先对dp数组进行初始化操作,只有一个骰子的时候,他的1-6的组合数都为1。

当n>=2的时候,数值的范围变成了[n,6*n],意味着我们可以直接从n开始计算,避免了多余的操作。

我们设置k为上一个组合中出现的点数,j为本次计算的组合数。

状态转移的核心在于当j-k>=n-1的时候,dp[i][j] += dp[i-1][j-k];

当我们把最后一行的组合数算完之后,我们可以直接利用组合数/总数来计算概率。

总的来说,这个题根本就是憨憨。。难就难在处理数据的边界问题。

原文地址:https://www.cnblogs.com/ZJPaang/p/12826245.html