面试题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];
当我们把最后一行的组合数算完之后,我们可以直接利用组合数/总数来计算概率。
总的来说,这个题根本就是憨憨。。难就难在处理数据的边界问题。