剑指Offer-60:n个骰子的点数
2018-03-27 15:01
337 查看
题目:
把n个骰子扔在地上,所有骰子朝上的一面的点数之和为s.输入n,打印出s的所有可能的值出现的概率。链接:
剑指Offer(第2版):P294思路标签:
算法:递归、动态规划解答:
1. 基于递归的方法,效率低
我们将大问题n个骰子的点数和,转化为求第1个和后面n-1个骰子;同时用一个数组来保存所有可能和出现的次数,注意是和出现的次数,即每次该和出现一次,对应的位置上就+1;
利用递归去求解,每一个骰子都有6种可能性,排列组合总共有6^n种可能;
结束条件是每次得到最后一个骰子的结果;
最后求概率注意int和double的转换。
class Solution { public: void PrintProbility(int number) { if (number < 1) return; int maxSum = number * g_maxValue; int * pProbabilities = new int[maxSum - number + 1]; for (int i = number; i <= maxSum; ++i) pProbabilities[i - number] = 0; Probability(number, pProbabilities); int total = pow((double)(g_maxValue), number); for (int i = number; i <= maxSum; ++i) { double ratio = (double)pProbabilities[i - number] / total; printf("%d: %e\n", i, ratio); } } void Probability(int number, int* pProbabilities) { for (int i = 1; i <= g_maxValue; ++i) Probability(number, number, i, pProbabilities); } void Probability(int original, int current, int sum, int* pProbabilities) { if (current == 1) pProbabilities[sum - original]++; else { for (int i = 1; i <= g_maxValue; ++i) Probability(original, current - 1, i + sum, pProbabilities); } } private: int g_maxValue = 6; };
2. 基于循环求骰子点数,性能较好(动态规划)
使用动态规划的思想其时间复杂度总是要小于递归的方法;我们设立数组,用数组中的第n个数表示骰子点数和为n的次数;
第k次投掷骰子的数可能为1~6中的任意一个数,如果我们假设第k次投掷骰子最终所有的和为n,那么和为n的次数就为前一次投掷(第k-1次投掷)和为n-1、n-2、n-3、n-4、n-5、n-6的次数的总和。
同时知道第1次投掷和为1,2,3,4,5,6的次数均为1;同时第k次投掷时,和为0、1、2…k-1将不会存在;
我们使用两个数组来交替进行,一个用来保存上一次投掷的和的次数,另一个以对方为基础用来计算当前投掷和的次数。每次用flag来交替。
class Solution { public: void PrintProbility(int number) { if (number < 1) return; int* pProbabilities[2]; int length = g_maxValue*number + 1; pProbabilities[0] = new int[length]; pProbabilities[1] = new int[length]; for (int i = 0; i < length; ++i) { pProbabilities[0][i] = 0; pProbabilities[1][i] = 1; } int flag = 0; for (int i = 1; i <= g_maxValue; ++i) pProbabilities[flag][i] = 1; for (int k = 2; k <= number; ++k) { for (int i = 0; i < k; ++i) pProbabilities[1 - flag][i] = 0; for (int i = k; i <= g_maxValue*k; ++i) { pProbabilities[1 - flag][i] = 0; for (int j = 1; j <= i && j <= g_maxValue; ++j) pProbabilities[1 - flag][i] += pProbabilities[flag][i - j]; } flag = 1 - flag; } double total = pow((double)g_maxValue, number); for (int i = number; i <= g_maxValue*number; ++i) { double ratio = (double)pProbabilities[flag][i] / total; printf("%d: %e\n", i, ratio); } delete[] pProbabilities[0]; delete[] pProbabilities[1]; } private: int g_maxValue = 6; };
相关文章推荐
- 剑指offer:n个骰子的点数(java)
- 【剑指offer】6.4抽象建模能力——面试题43:n个骰子的点数
- 剑指offer-第六章面试中的各项能力(n个骰子的点数)
- 剑指offer-面试题43-n个骰子的点数
- 剑指Offer:面试题43 n个骰子的点数
- 剑指offer43:n个骰子的点数
- 剑指Offer面试题43(Java版):n个骰子的点数
- 剑指offer 43. n个骰子的点数
- 剑指offer40--n个骰子点数和的概率
- 【剑指offer】面试题43:n个骰子的点数
- 剑指offer面试题43:n个骰子的点数
- 剑指offer——面试题43:n个骰子的点数
- 剑指 offer set 23 n 个骰子的点数
- 剑指Offer:n个骰子的点数
- 剑指offer 43-n个骰子的点数
- 剑指Offer面试题43(Java版):n个骰子的点数
- 剑指offer-面试题43:n个骰子的点数
- 【剑指offer】面试题43:n个骰子的点数
- 【剑指offer-Java版】43n个骰子的点数
- 剑指Offer之 - n个骰子的点数