剑指offer_掷骰子

题目描述:

扔 n 个骰子,向上面的数字之和为 S。给定 n,请列出所有可能的 S 值及其相应的概率。

样例:

给定 n = 1,返回 [ [1, 0.17], [2, 0.17], [3, 0.17], [4, 0.17], [5, 0.17], [6, 0.17]]

分析:

参考了一篇很好的博客:https://www.cnblogs.com/bozhou/p/6971081.html

题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入n,打印出S的所有可能的值出现的概率。

1.假设在n个骰子和点数和Sum的情况下,次数m = f(n,Sum) 

2.当然n-1块骰子的情况下,一般情况下可投出Sum-1、Sum-2、Sum-3、Sum-4、Sum-5、Sum-6的情况,即留给最后一块骰子1-6的投掷空间;

  (k-1,n-1):第k个骰子投了点数1

  (k-1,n-2):第k个骰子投了点数2

  (k-1,n-3):第k个骰子投了点数3

  ....

  (k-1,n-6):第k个骰子投了点数6

  AllPro =  f(n,Sum) = f(n-1,Sum-1) + f(n-1,Sum-2) + f(n-1,Sum-3) + f(n-1,Sum-4) + f(n-1,Sum-5) + f(n-1,Sum-6) 

3.特殊情况一,Sum - i < 1 *(n-1),即留给n-1块骰子的投掷空间已经比n-1块骰子的最小点数和还小了!

  AllPro =  f(n,Sum) = f(n-1,Sum-i) + f(n-1,Sum-i-1) + ... + f(n-1,Sum-5) + f(n-1,Sum-6) 

4.特殊情况二,Sum - i > 6 *(n-1),即留给n-1块骰子的投掷空间已经比n-1块骰子的最大点数和还大了!

  AllPro =  f(n,Sum) = f(n-1,Sum-1) + f(n-1,Sum-2) + ... + f(n-1,Sum-i) + f(n-1,Sum-i-1) 

 

例如 n = 1时:

  f(1,1) = f(1,2) = f(1,3) = f(1,4) = f(1,5) = f(1,6) = 1

而 n = 2时:

  f(2,2) = f(1,1) = 1

  f(2,3) = f(1,2) + f(1,1) = 2

  ...

  f(2,6) = f(1,5) + f(1,4) + f(1,3) + f(1,2) + f(1,1)

  f(2,7) = f(1,6) + f(1,5) + f(1,4) + f(1,3) + f(1,2) + f(1,1) = 6

  f(2,8) =  f(1,6) + f(1,5) + f(1,4) + f(1,3) + f(1,2) = 5

  ...

此时 f(2,2) 、f(2,3) ... f(2,6)就满足特殊情况一,而 f(2,8) 、f(2,9) ... f(2,12)就满足特殊情况二

 

public class Solution {
    /**
     * @param n an integer
     * @return a list of Map.Entry<sum, probability>
     */
    private TreeMap<Integer, Double> helper(TreeMap<Integer, Double> M){
        TreeMap<Integer, Double> newM = new TreeMap<>();
        double p = 1d/6;
        
        for(int i = 1; i <= 6; i++)
            for(int num : M.keySet()){
                int key = num + i;
                
                if(newM.containsKey(key)) newM.put(key, newM.get(key) + M.get(num)*p);
                
                else newM.put(key, M.get(num)*(1d/6));
            }
        
        return newM;
    }
     
    public List<Map.Entry<Integer, Double>> dicesSum(int n) {
        // Write your code here
        // Ps. new AbstractMap.SimpleEntry<Integer, Double>(sum, pro)
        // to create the pair
        TreeMap<Integer, Double> M = new TreeMap<>();
        double p = 1d/6;
        
        for(int i = 1; i <= 6; i++) M.put(i, p);
        
        for(int i = 2; i <= n; i++) M = helper(M);
        
        List<Map.Entry<Integer, Double>> ans = new ArrayList<>();
        
        for(Map.Entry<Integer, Double> e : M.entrySet()) ans.add(e);
        
        return ans;
    }
}
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值