60. n 个骰子的点数【难】
comments: true
difficulty: 简单
edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9860.%20n%E4%B8%AA%E9%AA%B0%E5%AD%90%E7%9A%84%E7%82%B9%E6%95%B0/README.md
面试题 60. n 个骰子的点数
题目描述
把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
解法
1.题目不太好理解,可以先看这个题:https://www.acwing.com/problem/content/76/
2.促进一点理解的题解:https://leetcode.cn/problems/nge-tou-zi-de-dian-shu-lcof/solutions/637778/jian-zhi-offer-60-n-ge-tou-zi-de-dian-sh-z36d/
方法一:动态规划
我们定义 f [ i ] [ j ] f[i][j] f[i][j] 表示投掷 i i i 个骰子,点数和为 j j j 的方案数。那么我们可以写出状态转移方程:
f [ i ] [ j ] = ∑ k = 1 6 f [ i − 1 ] [ j − k ] f[i][j] = \sum_{k=1}^6 f[i-1][j-k] f[i][j]=k=1∑6f[i−1][j−k]
其中 k k k 表示当前骰子的点数,而 f [ i − 1 ] [ j − k ] f[i-1][j-k] f[i−1][j−k] 表示投掷 i − 1 i-1 i−1 个骰子,点数和为 j − k j-k j−k 的方案数。
初始条件为 f [ 1 ] [ j ] = 1 f[1][j] = 1 f[1][j]=1,表示投掷一个骰子,点数和为 j j j 的方案数为 1 1 1。
最终,我们要求的答案即为 f [ n ] [ j ] 6 n \frac{f[n][j]}{6^n} 6nf[n][j],其中 n n n 为骰子个数,而 j j j 的取值范围为 [ n , 6 n ] [n, 6n] [n,6n]。
时间复杂度 O ( n 2 ) O(n^2) O(n2),空间复杂度 O ( 6 n ) O(6n) O(6n)。其中 n n n 为骰子个数。
Python3
class Solution:def dicesProbability(self, n: int) -> List[float]:f = [[0] * (6 * n + 1) for _ in range(n + 1)] #最大情况:投掷n个骰子,最大和为6nfor j in range(1, 7):f[1][j] = 1 #投掷1个骰子,各个和的方案数都是1for i in range(2, n + 1):for j in range(i, 6 * i + 1): #1)投掷i个筛子,和的范围为[i,6*i]for k in range(1, 7): #2)核心递推:方案数的累加if j - k >= 0:f[i][j] += f[i - 1][j - k]m = pow(6, n) #3)n个骰子的总方案数return [f[n][j] / m for j in range(n, 6 * n + 1)]
Java
class Solution {public double[] dicesProbability(int n) {int[][] f = new int[n + 1][6 * n + 1];for (int j = 1; j <= 6; ++j) {f[1][j] = 1;}for (int i = 2; i <= n; ++i) {for (int j = i; j <= 6 * i; ++j) {for (int k = 1; k <= 6; ++k) {if (j >= k) {f[i][j] += f[i - 1][j - k];}}}}double m = Math.pow(6, n);double[] ans = new double[5 * n + 1];for (int j = n; j <= 6 * n; ++j) {ans[j - n] = f[n][j] / m;}return ans;}
}
C++
class Solution {
public:vector<double> dicesProbability(int n) {int f[n + 1][6 * n + 1];memset(f, 0, sizeof f);for (int j = 1; j <= 6; ++j) {f[1][j] = 1;}for (int i = 2; i <= n; ++i) {for (int j = i; j <= 6 * i; ++j) {for (int k = 1; k <= 6; ++k) {if (j >= k) {f[i][j] += f[i - 1][j - k];}}}}vector<double> ans;double m = pow(6, n);for (int j = n; j <= 6 * n; ++j) {ans.push_back(f[n][j] / m);}return ans;}
};
Go
func dicesProbability(n int) (ans []float64) {f := make([][]int, n+1)for i := range f {f[i] = make([]int, 6*n+1)}for j := 1; j <= 6; j++ {f[1][j] = 1}for i := 2; i <= n; i++ {for j := i; j <= 6*i; j++ {for k := 1; k <= 6; k++ {if j >= k {f[i][j] += f[i-1][j-k]}}}}m := math.Pow(6, float64(n))for j := n; j <= 6*n; j++ {ans = append(ans, float64(f[n][j])/m)}return
}
JavaScript
/*** @param {number} n* @return {number[]}*/
var dicesProbability = function (n) {const f = Array.from({ length: n + 1 }, () => Array(6 * n + 1).fill(0));for (let j = 1; j <= 6; ++j) {f[1][j] = 1;}for (let i = 2; i <= n; ++i) {for (let j = i; j <= 6 * i; ++j) {for (let k = 1; k <= 6; ++k) {if (j >= k) {f[i][j] += f[i - 1][j - k];}}}}const ans = [];const m = Math.pow(6, n);for (let j = n; j <= 6 * n; ++j) {ans.push(f[n][j] / m);}return ans;
};
C#
public class Solution {public double[] DicesProbability(int n) {int[,] f = new int[n + 1, 6 * n + 1];for (int j = 1; j <= 6; ++j) {f[1, j] = 1;}for (int i = 2; i <= n; ++i) {for (int j = i; j <= 6 * i; ++j) {for (int k = 1; k <= 6; ++k) {if (j >= k) {f[i, j] += f[i - 1, j - k];}}}}double m = Math.Pow(6, n);double[] ans = new double[5 * n + 1];for (int j = n; j <= 6 * n; ++j) {ans[j - n] = f[n, j] / m;}return ans;}
}
Swift
class Solution {func dicesProbability(_ n: Int) -> [Double] {var f = Array(repeating: Array(repeating: 0, count: 6 * n + 1), count: n + 1)for j in 1...6 {f[1][j] = 1}if n > 1 {for i in 2...n {for j in i...(6 * i) {for k in 1...6 {if j >= k {f[i][j] += f[i - 1][j - k]}}}}}var m = 1.0for _ in 0..<n {m *= 6.0}var ans = Array(repeating: 0.0, count: 5 * n + 1)for j in n...(6 * n) {ans[j - n] = Double(f[n][j]) / m}return ans}
}
方法二:动态规划(空间优化)
我们可以发现,上述方法中的 f [ i ] [ j ] f[i][j] f[i][j] 的值仅与 f [ i − 1 ] [ j − k ] f[i-1][j-k] f[i−1][j−k] 有关,因此我们可以使用滚动数组的方式,将空间复杂度优化至 O ( 6 n ) O(6n) O(6n)。
Python3
class Solution:def dicesProbability(self, n: int) -> List[float]:f = [0] + [1] * 6for i in range(2, n + 1):g = [0] * (6 * i + 1)for j in range(i, 6 * i + 1):for k in range(1, 7):if 0 <= j - k < len(f):g[j] += f[j - k] #仅仅与投掷n-1个骰子的方案数 数组有关f = gm = pow(6, n)return [f[j] / m for j in range(n, 6 * n + 1)]
Java
class Solution {public double[] dicesProbability(int n) {int[] f = new int[7];Arrays.fill(f, 1);f[0] = 0;for (int i = 2; i <= n; ++i) {int[] g = new int[6 * i + 1];for (int j = i; j <= 6 * i; ++j) {for (int k = 1; k <= 6; ++k) {if (j - k >= 0 && j - k < f.length) {g[j] += f[j - k];}}}f = g;}double m = Math.pow(6, n);double[] ans = new double[5 * n + 1];for (int j = n; j <= 6 * n; ++j) {ans[j - n] = f[j] / m;}return ans;}
}
Go
func dicesProbability(n int) (ans []float64) {f := make([]int, 7)for i := 1; i <= 6; i++ {f[i] = 1}for i := 2; i <= n; i++ {g := make([]int, 6*i+1)for j := i; j <= 6*i; j++ {for k := 1; k <= 6; k++ {if j-k >= 0 && j-k < len(f) {g[j] += f[j-k]}}}f = g}m := math.Pow(6, float64(n))for j := n; j <= 6*n; j++ {ans = append(ans, float64(f[j])/m)}return
}
JavaScript
/*** @param {number} num* @return {number[]}*/
var dicesProbability = function (n) {let f = Array(7).fill(1);f[0] = 0;for (let i = 2; i <= n; ++i) {let g = Array(6 * i + 1).fill(0);for (let j = i; j <= 6 * i; ++j) {for (let k = 1; k <= 6; ++k) {if (j - k >= 0 && j - k < f.length) {g[j] += f[j - k];}}}f = g;}const ans = [];const m = Math.pow(6, n);for (let j = n; j <= 6 * n; ++j) {ans.push(f[j] / m);}return ans;
};
C#
public class Solution {public double[] DicesProbability(int n) {int[] f = new int[7];for (int i = 1; i <= 6; ++i) {f[i] = 1;}f[0] = 0;for (int i = 2; i <= n; ++i) {int[] g = new int[6 * i + 1];for (int j = i; j <= 6 * i; ++j) {for (int k = 1; k <= 6; ++k) {if (j - k >= 0 && j - k < f.Length) {g[j] += f[j - k];}}}f = g;}double m = Math.Pow(6, n);double[] ans = new double[5 * n + 1];for (int j = n; j <= 6 * n; ++j) {ans[j - n] = f[j] / m;}return ans;}
}
相关文章:
60. n 个骰子的点数【难】
comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9860.%20n%E4%B8%AA%E9%AA%B0%E5%AD%90%E7%9A%84%E7%82%B9%E6%95%B0/README.md 面试题 60. n 个骰子的点数 题目描述 把n个骰子扔在地上,所…...
高性能编程:无锁队列
目录 1. 无锁队列 1.1 无锁 1.1.1 阻塞(Blocking) 1.1.2 无锁(Lock-Free) 1.1.3 无等待(Wait-Free) 1.2 队列 1.2.1 链表实现的队列 1.2.2 数组实现的队列 1.2.3 混合实现的队列 1.3 多线程中的先…...

word标题排序编号错误
1.问题:word中有时会出现当前编号是2.1、3.1、4.1,下级编号却从1.1.1开始的情况,类似情况如下: 2.原因:此问题多为编号4.1、4.2和编号4.1.1使用的多级编号模板不一样,可以选中4.2,看下使用的多级…...
力扣---80. 删除有序数组中的重复项 II
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 说明&…...

一篇文章,讲清SQL的 joins 语法
SQL 中的不同 JOIN 类型: 1. (INNER)JOIN(内连接):返回两个表中具有匹配值的记录。 2. LEFT(OUTER)JOIN(左外连接):返回左表中的所有记录&#…...

设计模式之建造者模式(通俗易懂--代码辅助理解【Java版】)
文章目录 设计模式概述1、建造者模式2、建造者模式使用场景3、优点4、缺点5、主要角色6、代码示例:1)实现要求2)UML图3)实现步骤:1)创建一个表示食物条目和食物包装的接口2)创建实现Packing接口的实体类3&a…...

文生视频算法
文生视频 Sora解决问题:解决思路: CogVideoX解决问题:解决思路: Stable Video Diffusion(SVD)解决问题:解决思路: 主流AI视频技术框架: Sora Sora: A Review on Backg…...

LoRA: Low-Rank Adaptation Abstract
LoRA: Low-Rank Adaptation Abstract LoRA 论文的摘要介绍了一种用于减少大规模预训练模型微调过程中可训练参数数量和内存需求的方法,例如拥有1750亿参数的GPT-3。LoRA 通过冻结模型权重并引入可训练的低秩分解矩阵,减少了10,000倍的可训练参数…...

正点原子阿尔法ARM开发板-IMX6ULL(二)——介绍情况以及汇编
文章目录 一、裸机开发(21个)二、嵌入式Linux驱动例程三、汇编3.1 处理器内部数据传输指令3.2 存储器访问指令3.3 压栈和出栈指令3.4 跳转指令3.5 算术运算指令3.6 逻辑运算指令 一、裸机开发(21个) 二、嵌入式Linux驱动例程 三、…...
Unreal Engine——AI生成高精度的虚拟人物和环境(虚拟世界构建、电影场景生成)(一)
一、Unreal Engine 介绍 Unreal Engine(虚幻引擎)是由Epic Games开发的强大3D游戏开发引擎,自1998年首次发布以来,已经历了多个版本的迭代。虚幻引擎主要用于制作高品质的3D游戏,但也广泛用于电影、建筑、仿真等其他领…...

Emlog程序屏蔽用户IP拉黑名单插件
插件介绍 在很多时候我们需要得到用户的真实IP地址,例如,日志记录,地理定位,将用户信息,网站数据分析等,其实获取IP地址很简单,感兴趣的可以参考一下。 今天给大家带来舍力写的emlog插件:屏蔽…...

发送成绩的app或小程序推荐
老师们,新学期的第一次月考马上开始,是不是还在为如何高效、便捷地发布成绩而头疼呢?别担心,都2024年了,我们有更智能的方式来解决这个问题! 给大家安利一个超级实用的工具——易查分小程序。这个小程序简…...

51单片机-AT24C02(IIC总线介绍及其时序编写步骤)-第一节(下一节实战)
IIC开始通信(6大步) 我以前的文章也有对基本常用的通信协议讲解,如SPI UART IIC RS232 RS485 CAN的讲解,可前往主页查询,(2024.9.12,晚上20:53,将AT24C02存储芯片,掉电不…...

<<编码>> 第 11 章 逻辑门电路--或非门, 与非门, 缓冲器 示例电路
继电器或非门 info::操作说明 鼠标单击开关切换开合状态 闭合任意一个开关可使电路断开 primary::在线交互操作链接 https://cc.xiaogd.net/?startCircuitLinkhttps://book.xiaogd.net/code-hlchs-examples/assets/circuit/code-hlchs-ch11-19-nor-gate-by-relay.txt 或非门 i…...
股票api接口程序化报备,程序化交易监管对个人量化交易者有何影响
炒股自动化:申请官方API接口,散户也可以 python炒股自动化(0),申请券商API接口 python炒股自动化(1),量化交易接口区别 Python炒股自动化(2):获取…...
如何自己搭建一个网站?
今天的文章总结适合0基础,网站搭建的技巧和流程,哪怕你是小白,不会编程,也可以制作非常漂亮且实用的企业网站,如果想做个人博客更是不在话下。希望我的经验能帮助更多没有过多的经费、没有建站基础的朋友。用户跟着我的…...

虚拟化数据恢复—断电导致虚拟机目录项被破坏的数据恢复案例
虚拟化数据恢复环境: 某品牌服务器(部署VMware EXSI虚拟机)同品牌存储(存放虚拟机文件)。 虚拟化故障: 意外断电导致服务器上某台虚拟机无法正常启动。查看虚拟机配置文件发现这台故障虚拟机除了磁盘文件以…...

[机器学习]聚类算法
1 聚类算法简介 # 导包 from sklearn.datasets import make_blobs import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn.metrics import calinski_harabasz_score # 构建数据 x,ymake_blobs(n_samples1000,n_features2,centers[[-1,-1],[0,0],[1…...

JVM面试真题总结(七)
文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 解释GC的引用计数算法及其局限性 引用计数算法是一种非常直观、简…...

深入理解CASAtomic原子操作类详解
1.CAS介绍 什么是 CAS CAS(Compare And Swap,比较与交换),是非阻塞同步的实现原理,它是CPU硬件层面的一种指令,从CPU层面能保证"比较与交换"两个操作的原子性。CAS指令操作包括三个参数&#x…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...