文章目录

  • 题目描述
  • 代码 & 思路
    • 1. 二维数组(方便理解)
    • 2. 一维数组(节约空间)
    • 二刷

鸽了好久的打题博客~要继续补起来了!
今天不打题,明天变垃圾 QAQ

题目描述

  • 一眼就想先暴力枚举、或者递归呀~但是貌似会超时,这里就直接用dp了
  • 参考题解
  • 主要思路有点像跳台阶,也就是用上一轮次的和,来维护当前轮次的值

代码 & 思路

1. 二维数组(方便理解)

  • 举个例子吧:两个骰子得出来的值8,相当于:

    1. 一个骰子的2,再补上另一个的6
    2. 一个骰子的3,再补上另一个的5
    3. 一个骰子的4,再补上另一个的4
    4. 一个骰子的5,再补上另一个的3
    5. 一个骰子的6,再补上另一个的2
    6. 当然,一个骰子的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维,这里的行值是辅助了解当前状态):
    1. dp[2][12] = dp[1][11] + dp[1][10] + … + dp[1][6]
    2. dp[2][11] = dp[1][10] + dp[1][9] + … + dp[1][5]
    3. dp[2][2] = dp[1][1]
    4. 这也就是需要从后往前的原因,如果从前往后的话,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、动态规划)相关推荐

  1. 【LeetCode】剑指 Offer 60. n个骰子的点数

    [LeetCode]剑指 Offer 60. n个骰子的点数 文章目录 [LeetCode]剑指 Offer 60. n个骰子的点数 package offer;import java.util.Ar ...

  2. 剑指 Offer 60. n个骰子的点数(动态规划)

    [剑指 Offer 60. n个骰子的点数] 思路: \qquad题目其实不难,写这篇博客主要是记录下C++使用vector开多维数组. \qquad思路类似于走台阶,每次可以走1,2,3阶,问到每一 ...

  3. 97. Leetcode 剑指 Offer 60. n个骰子的点数 (动态规划-背包问题)

    步骤一.确定状态: 确定dp数组及下标含义 dp数组是一维,大小是[6*n+1], 这里要注意下,背包的容量会和物品的重量 有关系了,投掷n枚的骰子,背包的容量范围是[n,6n],用2枚想一下,出现的 ...

  4. 剑指 Offer 60. n个骰子的点数

    文章目录 题目地址 代码 递推公式 空间优化 运行结果通过 题目地址 力扣https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof/ 代 ...

  5. 【LeetCode】剑指 Offer 10- II. 青蛙跳台阶问题

    [LeetCode]剑指 Offer 10- II. 青蛙跳台阶问题 文章目录 [LeetCode]剑指 Offer 10- II. 青蛙跳台阶问题 一.动态规划 总结 一.动态规划 class So ...

  6. 【leetcode】 剑指 Offer学习计划(java版本含注释)(上)

    目录 前言 第一天(栈与队列) 剑指 Offer 09. 用两个栈实现队列(简单) 剑指 Offer 30. 包含min函数的栈(简单) 第二天(链表) 剑指 Offer 06. 从尾到头打印链表(简 ...

  7. 《LeetCode力扣练习》剑指 Offer 30. 包含min函数的栈 Java

    <LeetCode力扣练习>剑指 Offer 30. 包含min函数的栈 Java 一.资源 题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调 ...

  8. 《LeetCode力扣练习》剑指 Offer 11. 旋转数组的最小数字 Java

    <LeetCode力扣练习>剑指 Offer 11. 旋转数组的最小数字 Java 一.资源 题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 给你一个可能存在 ...

  9. 《LeetCode力扣练习》剑指 Offer 10- I. 斐波那契数列 Java

    <LeetCode力扣练习>剑指 Offer 10- I. 斐波那契数列 Java 一.资源 题目: 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N) ...

最新文章

  1. 1.1 Friday the Thirteenth
  2. VS2010中获取并调用CRM2011中的工作流
  3. 计算机统计字符数,如何在Word中统计相同字符(文字)出现的个数 -电脑资料
  4. 报错:“-bash: git: 未找到命令”
  5. leetcode516. 最长回文子序列(动态规划)
  6. java定义一个course类,java集合,定义两个类,学生Student和课程Course,课程被学生选修,请在课程类中提供以下功能:...
  7. (08)FPGA时钟概念
  8. 第二阶段第五次站立会议
  9. CentOS7下安装JDK及IDEA
  10. 圣殿骑士的一篇关于WPF的培训好文,WPF应用与团队开发(转)
  11. sublime text3 炫酷主题
  12. python找不到csv文件路径_无法识别csv的构造文件路径。但文件是
  13. JavaScript中的数组方法总结+详解
  14. WeX5 APP发布及版本升级注意事项
  15. Vant上传多个图片或视频,更改视频预览图
  16. java SSM 班级同学录聚会报名网站-毕业设计源码介绍
  17. 美国计算机专业本科毕业薪酬,美国各专业本科毕业生薪酬盘点
  18. 运用javascript的成员访问特性来实现通用版的兼容所有浏览器的打开对话框功能...
  19. spring-mvc - validation - 数据验证
  20. ajax 传对象数组到后台

热门文章

  1. 蜂鸟开发板 linux,蜂鸟E203系列——Linux下运行hello world例程
  2. freemark循环map_freemarker中循环map根据key值得value 报错
  3. vue function (i)第一次点击不执行_vue下$nextTick及原理浅析
  4. AttributeError: module 'tensorflow' has no attribute 'FIFOQueue'
  5. Verilog HDL语言实现ROM、RAM+有限状态机
  6. 图像处理中的通信原理——冈萨雷斯读书笔记(一)
  7. 转载:实用 FRIDA 进阶 --- objection :内存漫游、hook anywhere、抓包
  8. 设计原本思维导图笔记
  9. matlab算hht,关于MATLAB中HHT谱图的问题【百度知道悬赏100积分】
  10. matlab 数值格式转换,Matlab字符串转换及数值格式转换