Skip to content
本页目录

60-n个骰子的点数

题目描述

https://leetcode.cn/problems/nge-tou-zi-de-dian-shu-lcof

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

你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。

示例 1:

输入: 1
输出: [0.16667,0.16667,0.16667,0.16667,0.16667,0.16667]

示例2:

输入: 2
输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]

限制:

  • 1 <= n <= 11

思路:组合

组合,dfs枚举每个骰子出现的次数,放入到hash表中。
最后再统计出每种情况出现的概率。

实现代码

csharp
public class Solution {

	Dictionary<int, int> dict;
	int total = 0;

	private int getSum(int[] bits){
        int sum = 0;
        for(int i=0; i<bits.Length; i++){
            sum+=bits[i];
        }
        return sum;
	}

	private void dfs(int index, int[] bits){
		if(index == bits.Length){
			//循环结束
			int key = getSum(bits);
			if(!dict.ContainsKey(key)){
				dict.Add(key,1);
			}
			else{
				dict[key]++;
			}
			total++;
            return;
		}

		for(int i=1; i<=6; i++){
			bits[index] = i;
			dfs(index+1,bits);
		}
	}

    public double[] DicesProbability(int n) {
    	dict = new Dictionary<int, int>();
    	int[] bits = new int[n];
    	dfs(0,bits);
    	//输出
    	double[] result = new double[dict.Keys.Count];
        int index = 0;
        foreach(int key in dict.Keys)
    	{
            Console.WriteLine("key{0},index{1}",key,index);
    		result[index] = (double) dict[key] / total;
            index++;
    	}
    	return result;
    }
}

优化回溯 个数可以提前得知,每一份的数据也可以提前得知

1个筛子,出点数是 1 - 6, 两个骰子,最小是 2 最大是 6 * 2, 三个骰子最小是3,最大是 6 * 3. 所以最大的个数已经确定,即 count = 6 * n - n + 1

点数组合的总数就是 6^n ,即 1个骰子就是6种组合, 再来一个骰子就是 6 * 6 ,再来一个骰子就是 6 * 6 * 6

csharp
public class Solution {

	int curSum = 0;
	int count = 0;
    int total = 1;
	double[] result ;

	private void dfs(int index, int n){
		if(index == n){
			result[curSum-n] += 1.0 / total;
            return;
		}

		for(int i=1; i<=6; i++){
			curSum+=i;
			dfs(index+1,n);
			curSum-=i;
		}
	}

	public double[] DicesProbability(int n) {
		count = 6*n - n + 1;
        for(int i=0;i<n;i++){
            total *=6;
        }
		result = new double[count];
		dfs(0,n);
		return result;
	}
}

思路2:动态规划

https://leetcode.cn/problems/nge-tou-zi-de-dian-shu-lcof/solution/jian-zhi-offer-60-n-ge-tou-zi-de-dian-sh-z36d/

csharp
public class Solution {
	public double[] DicesProbability(int n){
		double[] dp = new double[6];
		Array.Fill(dp,1.0/6.0);
		for(int i=2; i<=n; i++){
			double[] tmp = new double[6 * i - i + 1]; //总情况数
			for(int j=0; j<dp.Length; j++){
				for(int k=0; k<6; k++){
					tmp[j+k] += dp[j] / 6.0; //每种组合的概率都是前面的概率 * 1/6 ,但是和相同的会累计,比如 2,3 和 3,2的概率会累计到一起
				}
			}
			dp = tmp;
		}
        return dp;
	}
}

复习:20220509

csharp
public class Solution {
    public double[] DicesProbability(int n) {
        double[] dp = new double[6]; //初始化概率
        Array.Fill(dp,1.0/6.0);
        for(int i=2; i<=n; i++){
            int count = 5 * i + 1;
            double[] dp2 = new double[count];
            for(int j=0; j<dp.Length; j++){
                for(int k=0; k<6; k++){
                    dp2[j+k] += dp[j] / 6.0;
                }
            }
            dp = dp2;
        }
        return dp;
    }
}

Released under the MIT License.