zoukankan      html  css  js  c++  java
  • [leetCode]剑指 Offer 60. n个骰子的点数

    在这里插入图片描述

    解法一 递归

    class Solution {
        // 提高程序扩展性
        public int maxValue = 6;
        public double[] twoSum(int n) {
            if (n < 1) return new double[]{};
            // 最大和为6n,最小和为n,可能的和有 6n - n + 1 种
            int maxSum = n * maxValue;
            // 定义一个长度为6n - n + 1的数组,每个元素代表每个可能的和s的出现次数
            int[] probabilities = new int[maxSum - n + 1];
    
            probability(n, probabilities);
            
            double[] ans = new double[probabilities.length];
            // 由排列组合可知n个骰子排列数次数为6^n
            double total = Math.pow(maxValue, n);
            for (int i = n; i <= maxSum ; i++) {
                ans[i - n] = (double)probabilities[i - n] / total;
            }
            return ans;
        }
    
        private void probability(int n, int[] probabilities) {
            // 把n个骰子分成两部分:第一部分一个,有1-6种;第二部分n-1个。
            // 计算1-6中每个点数与剩下n-1个骰子的点数和
            for (int i = 1; i <= maxValue; i++) {
                probability(n, n, i, probabilities);
            }
        }
    
        // current 为当前剩余的骰子数; sum为当前的和
        private void probability(int n, int current, int sum, int[] probabilities) {
            if (current == 1) {
                probabilities[sum - n]++;
            } else {
                for (int i = 1; i <= maxValue; i++) {
                    probability(n, current - 1, sum + i, probabilities);
                }
            }
        }
    }
    

    解法二 动态规化

    class Solution {
        // 提高程序扩展性
        public int maxValue = 6;
        public double[] twoSum(int n) {
            if (n < 1) return new double[]{};
            // 最大和为6n,最小和为n,可能的和有 6n - n + 1 种
            int maxSum = n * maxValue;
    
            int[][] probablilities = new int[2][maxSum + 1];
            Arrays.fill(probablilities[0], 0);
            Arrays.fill(probablilities[1], 0);
            int flag = 0;
    
            // 第一轮循环:只有一个骰子时1~6每个数字出现的次数为1
            for (int i = 1; i <= maxValue; i++) 
                probablilities[flag][i] = 1;
            // 第二轮循环: 每次增加一个骰子,范围为2~n
            for (int k  = 2; k <= n; k++) {
                // 另一个数组和为前k-1为的数字出现次数为0
                for (int i = 0; i < k; ++i) 
                    probablilities[1-flag][i] = 0;
                // 计算k~maxValue * k之间每个和出现的次数
                for (int i = k; i <= maxValue * k; i++) {
                    // 先初始化为0
                    probablilities[1-flag][i] = 0;
                    for (int j = 1; j <= i && j <= maxValue; j++) {
                        probablilities[1-flag][i] += probablilities[flag][i-j];
                    }
                }
                // 交换数组
                flag = 1-flag;
            }
            double total = Math.pow(maxValue, n);
            double[] ans = new double[maxSum - n + 1];
            for (int i = n; i <= maxSum; i++) {
                ans[i-n] = probablilities[flag][i]/total;
            }
            return ans;
        }
    }
    
  • 相关阅读:
    PHP流程控制考察点
    PHP运算符考察点
    PHP的魔术常量
    android窗体溢出WindowManager$BadTokenException: Unable to add window -- token null is not for an applica
    android网络访问异常java.lang.SecurityException: Permission denied (missing INTERNET permission?)
    快速排序算法思想
    播放Assets下的指定音频时,变成播放所有音频了
    python-01-Python环境搭建
    eclipse安装svn
    DOM children方法
  • 原文地址:https://www.cnblogs.com/PythonFCG/p/13859928.html
Copyright © 2011-2022 走看看