当前位置: 首页 > news >正文

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=16f[i1][jk]

其中 k k k 表示当前骰子的点数,而 f [ i − 1 ] [ j − k ] f[i-1][j-k] f[i1][jk] 表示投掷 i − 1 i-1 i1 个骰子,点数和为 j − k j-k jk 的方案数。

初始条件为 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[i1][jk] 有关,因此我们可以使用滚动数组的方式,将空间复杂度优化至 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个骰子扔在地上&#xff0c;所…...

高性能编程:无锁队列

目录 1. 无锁队列 1.1 无锁 1.1.1 阻塞&#xff08;Blocking&#xff09; 1.1.2 无锁&#xff08;Lock-Free&#xff09; 1.1.3 无等待&#xff08;Wait-Free&#xff09; 1.2 队列 1.2.1 链表实现的队列 1.2.2 数组实现的队列 1.2.3 混合实现的队列 1.3 多线程中的先…...

word标题排序编号错误

1.问题&#xff1a;word中有时会出现当前编号是2.1、3.1、4.1&#xff0c;下级编号却从1.1.1开始的情况&#xff0c;类似情况如下&#xff1a; 2.原因&#xff1a;此问题多为编号4.1、4.2和编号4.1.1使用的多级编号模板不一样&#xff0c;可以选中4.2&#xff0c;看下使用的多级…...

力扣---80. 删除有序数组中的重复项 II

给你一个有序数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 说明&…...

一篇文章,讲清SQL的 joins 语法

SQL 中的不同 JOIN 类型&#xff1a; 1. &#xff08;INNER&#xff09;JOIN&#xff08;内连接&#xff09;&#xff1a;返回两个表中具有匹配值的记录。 2. LEFT&#xff08;OUTER&#xff09;JOIN&#xff08;左外连接&#xff09;&#xff1a;返回左表中的所有记录&#…...

设计模式之建造者模式(通俗易懂--代码辅助理解【Java版】)

文章目录 设计模式概述1、建造者模式2、建造者模式使用场景3、优点4、缺点5、主要角色6、代码示例&#xff1a;1&#xff09;实现要求2&#xff09;UML图3)实现步骤&#xff1a;1&#xff09;创建一个表示食物条目和食物包装的接口2&#xff09;创建实现Packing接口的实体类3&a…...

文生视频算法

文生视频 Sora解决问题&#xff1a;解决思路&#xff1a; CogVideoX解决问题&#xff1a;解决思路&#xff1a; Stable Video Diffusion&#xff08;SVD&#xff09;解决问题&#xff1a;解决思路&#xff1a; 主流AI视频技术框架&#xff1a; Sora Sora: A Review on Backg…...

LoRA: Low-Rank Adaptation Abstract

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

正点原子阿尔法ARM开发板-IMX6ULL(二)——介绍情况以及汇编

文章目录 一、裸机开发&#xff08;21个&#xff09;二、嵌入式Linux驱动例程三、汇编3.1 处理器内部数据传输指令3.2 存储器访问指令3.3 压栈和出栈指令3.4 跳转指令3.5 算术运算指令3.6 逻辑运算指令 一、裸机开发&#xff08;21个&#xff09; 二、嵌入式Linux驱动例程 三、…...

Unreal Engine——AI生成高精度的虚拟人物和环境(虚拟世界构建、电影场景生成)(一)

一、Unreal Engine 介绍 Unreal Engine&#xff08;虚幻引擎&#xff09;是由Epic Games开发的强大3D游戏开发引擎&#xff0c;自1998年首次发布以来&#xff0c;已经历了多个版本的迭代。虚幻引擎主要用于制作高品质的3D游戏&#xff0c;但也广泛用于电影、建筑、仿真等其他领…...

Emlog程序屏蔽用户IP拉黑名单插件

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

发送成绩的app或小程序推荐

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

51单片机-AT24C02(IIC总线介绍及其时序编写步骤)-第一节(下一节实战)

IIC开始通信&#xff08;6大步&#xff09; 我以前的文章也有对基本常用的通信协议讲解&#xff0c;如SPI UART IIC RS232 RS485 CAN的讲解&#xff0c;可前往主页查询&#xff0c;&#xff08;2024.9.12,晚上20&#xff1a;53&#xff0c;将AT24C02存储芯片&#xff0c;掉电不…...

<<编码>> 第 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接口程序化报备,程序化交易监管对个人量化交易者有何影响

炒股自动化&#xff1a;申请官方API接口&#xff0c;散户也可以 python炒股自动化&#xff08;0&#xff09;&#xff0c;申请券商API接口 python炒股自动化&#xff08;1&#xff09;&#xff0c;量化交易接口区别 Python炒股自动化&#xff08;2&#xff09;&#xff1a;获取…...

如何自己搭建一个网站?

今天的文章总结适合0基础&#xff0c;网站搭建的技巧和流程&#xff0c;哪怕你是小白&#xff0c;不会编程&#xff0c;也可以制作非常漂亮且实用的企业网站&#xff0c;如果想做个人博客更是不在话下。希望我的经验能帮助更多没有过多的经费、没有建站基础的朋友。用户跟着我的…...

虚拟化数据恢复—断电导致虚拟机目录项被破坏的数据恢复案例

虚拟化数据恢复环境&#xff1a; 某品牌服务器&#xff08;部署VMware EXSI虚拟机&#xff09;同品牌存储&#xff08;存放虚拟机文件&#xff09;。 虚拟化故障&#xff1a; 意外断电导致服务器上某台虚拟机无法正常启动。查看虚拟机配置文件发现这台故障虚拟机除了磁盘文件以…...

[机器学习]聚类算法

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面试真题总结(七)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 解释GC的引用计数算法及其局限性 引用计数算法是一种非常直观、简…...

深入理解CASAtomic原子操作类详解

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

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

02.运算符

目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&&#xff1a;逻辑与 ||&#xff1a;逻辑或 &#xff01;&#xff1a;逻辑非 短路求值 位运算符 按位与&&#xff1a; 按位或 | 按位取反~ …...

Windows 下端口占用排查与释放全攻略

Windows 下端口占用排查与释放全攻略​ 在开发和运维过程中&#xff0c;经常会遇到端口被占用的问题&#xff08;如 8080、3306 等常用端口&#xff09;。本文将详细介绍如何通过命令行和图形化界面快速定位并释放被占用的端口&#xff0c;帮助你高效解决此类问题。​ 一、准…...

VSCode 使用CMake 构建 Qt 5 窗口程序

首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...