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

1.题目

面试题60:n个骰子的点数_第1张图片

2.解法1(递归法)

一个骰子有for(i=1;i <=6;i++), 选择1个,剩余n-1个骰子,接着再选1个,剩余n-2,所以使用递归法来做


public class Solution{
     

    // 骰子面最大值
    private int maxVal = 6;
    // 骰子的个数
    private int number;
    // 包含和的数组
    int[] pProbability;

    public void printProbability(int number){
     
        // 没有骰子
        if(number < 1){
     
            return;
        }

        this.number = number;

        // 所有和的最大值
        int maxSum = maxVal * number;

        /**
         * s的和最大为6n,最小为n,所以总共有6n-n+1的可能性
         * 我们将s的count保存在[s-n]的位置
         */

        this.pProbability = new int[maxSum - number + 1];
        calProbability(number, 0);


        /**
         * allCoun代表的是有这么多值会出现,但是总的出现次数是6的number次方
         */
        double total = Math.pow(maxVal, number);
        for (int i = 0; i < pProbability.length; i++) {
     
            System.out.print(pProbability[i] / total + " ");
        }
    }

    /**
     * current代表骰子的剩余个数
     * sum代表截止到目前,骰子得总和
     */
    public void calProbability(int current, int sum){
     
        // 骰子的和已经计算完
        if(current == 0) {
     
            pProbability[sum - number]++;
        }else{
     
            // 每个骰子拥有6个值
            for (int i = 1; i <= maxVal; i++) {
     
                calProbability(current-1, sum + i);
            }
        }
    }
    public static void main(String[] args) {
     
        Solution sn = new Solution();
        sn.printProbability(2);
    }
}

递归会重复计算很多的值,这里使用的是自顶向下的递归法,不能使用自底向上的递归法(因为返回的值很多)不能向判断是不是平衡树的那道题学习
添加链接描述

3.解法2(动态规划)

public class Solution{
     
    public double[] twoSum(int n) {
     
            int dp[][]=new int[n+1][6*n+1];//表示i个骰子掷出s点的次数
            for(int i=1;i<=6;i++) {
     
                dp[1][i]=1;//表示一个骰子掷出i点的次数为1
            }
            for(int i=2;i<=n;i++) {
     //表示骰子的个数
                for(int s=i;s<=6*i;s++) {
     //表示可能会出现的点数之和
                    for(int j=1;j<=6;j++) {
     //表示当前这个骰子可能掷出的点数
                        if(s-j<i-1) {
     //当总数还没有j大时,就不存在这种情况
                            break;
                        }
                        dp[i][s]+=dp[i-1][s-j];//当前n个骰子出现的点数之和等于前一次出现的点数之和加上这一次出现的点数
                    }
                }
            }
            double total = Math.pow((double)6,(double)n);//掷出n次点数出现的所有情况
            double[] ans = new double[5*n+1];//因为最大就只会出现5*n+1中点数
            for(int i=n;i<=6*n;i++){
     
                ans[i-n]=((double)dp[n][i])/total;//第i小的点数出现的概率
            }
            return ans;
        }
}}

面试题60:n个骰子的点数_第2张图片
时间复杂度和空间复杂度均为O(n^2)

你可能感兴趣的:(Leetcode打卡)