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…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...

Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...

spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
2.2.2 ASPICE的需求分析
ASPICE的需求分析是汽车软件开发过程中至关重要的一环,它涉及到对需求进行详细分析、验证和确认,以确保软件产品能够满足客户和用户的需求。在ASPICE中,需求分析的关键步骤包括: 需求细化:将从需求收集阶段获得的高层需…...