【LeetCode笔记】剑指 Offer 60. n个骰子的点数(Java、动态规划)
文章目录
- 题目描述
- 代码 & 思路
- 1. 二维数组(方便理解)
- 2. 一维数组(节约空间)
- 二刷
鸽了好久的打题博客~要继续补起来了!
今天不打题,明天变垃圾 QAQ
题目描述
- 一眼就想先暴力枚举、或者递归呀~但是貌似会超时,这里就直接用dp了
- 参考题解
- 主要思路有点像跳台阶,也就是用上一轮次的和,来维护当前轮次的值
代码 & 思路
1. 二维数组(方便理解)
- 举个例子吧:两个骰子得出来的值8,相当于:
- 一个骰子的2,再补上另一个的6
- 一个骰子的3,再补上另一个的5
- 一个骰子的4,再补上另一个的4
- 一个骰子的5,再补上另一个的3
- 一个骰子的6,再补上另一个的2
- 当然,一个骰子的1,再补上另一个的7 这种情况是不存在的,所以只有5种情况可行。
也就是说 dp[2][8] = dp[1][2] + dp[1][3] + dp[1][4] + dp[1][5]+ dp[1][6]
- 按照这么一个思路,我们就可以得出下面的代码:
class Solution {public double[] dicesProbability(int n) {// 第一行、最后一列舍弃,方便下标理解// dp[骰子数][可投出点数] = 对应次数double[][] dp = new double[n + 1][6 * n + 1];// 初始化for(int i = 1; i <= 6; i++) {dp[1][i] = 1;}// dp 过程for(int i = 2; i <= n; i++) {// 范围[i, 6 * i]for(int j = i; j <= 6 * i; j++) {// 取上一层的前6个for(int k = 1; k <= 6; k++) {// 取不到6个则有多少取多少if(j - k <= 0) {break;}// 状态转移方程 dp[i][j] += dp[i - 1][j - k];}}}// 结束,取答案double all = Math.pow(6, n);double[] ans = new double[5 * n + 1];for(int i = 0; i < ans.length; i++) {ans[i] = dp[n][i + n] / all;}return ans;}
}
2. 一维数组(节约空间)
- 在上一个方法的基础上,我们知道:第 n 轮的值,只和第 n - 1 轮的值相关
- (还是得去上面链接的题解结合动图理解)
- 经过思考,可以发现其实按照从后往前的顺序进行数组更新,就只需要一维数组即可:
- 举个例子(实际还是1维,这里的行值是辅助了解当前状态):
- dp[2][12] = dp[1][11] + dp[1][10] + … + dp[1][6]
- dp[2][11] = dp[1][10] + dp[1][9] + … + dp[1][5]
- …
- dp[2][2] = dp[1][1]
- 这也就是需要从后往前的原因,如果从前往后的话,dp[2][12]就取不到dp[1][11]的值了。从后往前可以实现无后效性~
- 那么进行一个空间上的优化,可以得到以下代码:
class Solution {public double[] dicesProbability(int n) {// 0 下标不取,一共 6 * n 个格子double[] dp = new double[6 * n + 1];// 初始化,全为1for(int i = 1; i <= 6; i++) {dp[i] = 1;}// 2个、3个...n个骰子,以此类推for(int i = 2; i <= n; i++) {// 从后往前,可推n个骰子范围[n, 6 * n]for(int j = 6 * i; j >= i; j--) {// 给新的格子赋值dp[j] = 0;// 获取前六个格子的值(类似走楼梯)for(int k = 1; k <= 6; k++) {// 过于倒退的情况,结束(不一定都能取6个)if(j - k < i - 1) {break;}// 累加前面的格子值dp[j] += dp[j - k];}}}// 获取答案double all = Math.pow(6, n);double[] ans = new double[5 * n + 1];for(int i = 0; i < ans.length; i++) {ans[i] = dp[n + i] / all;}return ans;}
}
二刷
- O(n2n^2n2)、O(n2n^2n2)
class Solution {public double[] dicesProbability(int n) {// 1. dp初始化int[][] ans = new int[n + 1][6 * n + 1];for(int i = 1; i <= 6; i++) {ans[1][i] = 1;}// 2. dp 过程 O(n^2)for(int i = 2; i <= n; i++) {for(int j = i; j <= i * 6; j++) {for(int k = 1; k <= 6 && j - k >= i - 1; k++) {ans[i][j] += ans[i - 1][j - k];}}}// 3. 获取答案double[] myAns = new double[5 * n + 1];for(int i = 0; i < myAns.length; i++) {myAns[i] = ans[n][i + n] / Math.pow(6, n);;}return myAns;}
}
- O(n2n^2n2)、O(nnn)
class Solution {public double[] dicesProbability(int n) {// 1. dp初始化int[] ans = new int[6 * n + 1];for(int i = 1; i <= 6; i++) {ans[i] = 1;}// 2. dp 过程 O(n^2)for(int i = 2; i <= n; i++) {for(int j = 6 * i; j >= i; j--) {ans[j] = 0;for(int k = 1; k <= 6 && j - k >= i - 1; k++) {ans[j] += ans[j - k];}}}// 3. 获取答案double[] myAns = new double[5 * n + 1];for(int i = 0; i < myAns.length; i++) {myAns[i] = ans[i + n] / Math.pow(6, n);;}return myAns;}
}
【LeetCode笔记】剑指 Offer 60. n个骰子的点数(Java、动态规划)相关推荐
- 【LeetCode】剑指 Offer 60. n个骰子的点数
[LeetCode]剑指 Offer 60. n个骰子的点数 文章目录 [LeetCode]剑指 Offer 60. n个骰子的点数 package offer;import java.util.Ar ...
- 剑指 Offer 60. n个骰子的点数(动态规划)
[剑指 Offer 60. n个骰子的点数] 思路: \qquad题目其实不难,写这篇博客主要是记录下C++使用vector开多维数组. \qquad思路类似于走台阶,每次可以走1,2,3阶,问到每一 ...
- 97. Leetcode 剑指 Offer 60. n个骰子的点数 (动态规划-背包问题)
步骤一.确定状态: 确定dp数组及下标含义 dp数组是一维,大小是[6*n+1], 这里要注意下,背包的容量会和物品的重量 有关系了,投掷n枚的骰子,背包的容量范围是[n,6n],用2枚想一下,出现的 ...
- 剑指 Offer 60. n个骰子的点数
文章目录 题目地址 代码 递推公式 空间优化 运行结果通过 题目地址 力扣https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof/ 代 ...
- 【LeetCode】剑指 Offer 10- II. 青蛙跳台阶问题
[LeetCode]剑指 Offer 10- II. 青蛙跳台阶问题 文章目录 [LeetCode]剑指 Offer 10- II. 青蛙跳台阶问题 一.动态规划 总结 一.动态规划 class So ...
- 【leetcode】 剑指 Offer学习计划(java版本含注释)(上)
目录 前言 第一天(栈与队列) 剑指 Offer 09. 用两个栈实现队列(简单) 剑指 Offer 30. 包含min函数的栈(简单) 第二天(链表) 剑指 Offer 06. 从尾到头打印链表(简 ...
- 《LeetCode力扣练习》剑指 Offer 30. 包含min函数的栈 Java
<LeetCode力扣练习>剑指 Offer 30. 包含min函数的栈 Java 一.资源 题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调 ...
- 《LeetCode力扣练习》剑指 Offer 11. 旋转数组的最小数字 Java
<LeetCode力扣练习>剑指 Offer 11. 旋转数组的最小数字 Java 一.资源 题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 给你一个可能存在 ...
- 《LeetCode力扣练习》剑指 Offer 10- I. 斐波那契数列 Java
<LeetCode力扣练习>剑指 Offer 10- I. 斐波那契数列 Java 一.资源 题目: 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N) ...
最新文章
- 1.1 Friday the Thirteenth
- VS2010中获取并调用CRM2011中的工作流
- 计算机统计字符数,如何在Word中统计相同字符(文字)出现的个数 -电脑资料
- 报错:“-bash: git: 未找到命令”
- leetcode516. 最长回文子序列(动态规划)
- java定义一个course类,java集合,定义两个类,学生Student和课程Course,课程被学生选修,请在课程类中提供以下功能:...
- (08)FPGA时钟概念
- 第二阶段第五次站立会议
- CentOS7下安装JDK及IDEA
- 圣殿骑士的一篇关于WPF的培训好文,WPF应用与团队开发(转)
- sublime text3 炫酷主题
- python找不到csv文件路径_无法识别csv的构造文件路径。但文件是
- JavaScript中的数组方法总结+详解
- WeX5 APP发布及版本升级注意事项
- Vant上传多个图片或视频,更改视频预览图
- java SSM 班级同学录聚会报名网站-毕业设计源码介绍
- 美国计算机专业本科毕业薪酬,美国各专业本科毕业生薪酬盘点
- 运用javascript的成员访问特性来实现通用版的兼容所有浏览器的打开对话框功能...
- spring-mvc - validation - 数据验证
- ajax 传对象数组到后台
热门文章
- 蜂鸟开发板 linux,蜂鸟E203系列——Linux下运行hello world例程
- freemark循环map_freemarker中循环map根据key值得value 报错
- vue function (i)第一次点击不执行_vue下$nextTick及原理浅析
- AttributeError: module 'tensorflow' has no attribute 'FIFOQueue'
- Verilog HDL语言实现ROM、RAM+有限状态机
- 图像处理中的通信原理——冈萨雷斯读书笔记(一)
- 转载:实用 FRIDA 进阶 --- objection :内存漫游、hook anywhere、抓包
- 设计原本思维导图笔记
- matlab算hht,关于MATLAB中HHT谱图的问题【百度知道悬赏100积分】
- matlab 数值格式转换,Matlab字符串转换及数值格式转换