LintCode2016年8月22日算法比赛----骰子求和
骰子求和
题目描述
扔n个骰子,向上面的数字之和为 S 。给定 Given n,请列出所有可能的 S 值及其相应的概率。
样例
给定n=1,返回
[ [1, 0.17], [2, 0.17], [3, 0.17], [4, 0.17], [5, 0.17], [6, 0.17]]。
算法分析
该题目刚开始的标记为简单,所以我做完两道简单题目后直接就看了这道题目,结果被卡在这里了。后来实现了完整的算法,结果提交只是通过了一部分的数据测试。看看还剩2分钟就结束了,焦急了,回头再去看题目列表,发现该题的难度级别又被标记为困难了,而之前标记为困难的平面列表,又被标记为简单了。进去一看,果然很简单,5分钟内实现了算法,在Eclipse测试,然后提交,Accepted!。结果比赛也已经结束了,只算是做对了两道题。我了个去!主办方是否要检讨检讨?
不闲扯了,分析算法:
该问题的解题思路应该是采用递归的方法:给定n个骰子,那么可投掷出的数字为n6n。可能有人会疑惑n6n中会不会有某个数字骰子表达不出来,好疑惑,答案是不会,证明如下:假设有n个相同的单个容量为6的豌豆筒,我们有6n颗豌豆,那么这6n颗豌豆能且正好能放进这n个豌豆筒中,说明n个骰子可以表达出6n;现在从任意筒中取出一颗豌豆,筒中还剩6n-1颗豌豆,说明n颗骰子可以表达出6n-1;如果某个筒中只剩一颗豌豆了,那么我们再次取豌豆的时候就不从里面取了;重复一颗一颗地取豌豆,直到每个筒中只剩下一颗豌豆,这是筒中总共有n颗豌豆,说明n个骰子可以表达n。而从6n到n的过程中,因为我们是一颗一颗豌豆取出的,所以6n-1到n+1这些颗数都曾在筒中出现过。因此n颗骰子能表达6n到n的所有数字。
n个骰子总共可以表达的情况有Math.pow(6,n)种。考虑n个骰子可以表达num的情况数:
如果第一骰子投出1,那么我们只需关心剩下的n-1个骰子能表达的num-1的情况数;如果第一个骰子投出了2,那么我们只需关心剩下的n-1个骰子能表达的num-2的情况数,依此类推;当然要注意,第一个骰子最多投出6。这里就用到了递归的思想。求n个骰子投出num的情况数的时候,需要递归求n-1个骰子投出num-1,num-2,num-3...的情况,而求n-1个骰子投出num-1的情况数的时候,需要递归求n-2个骰子投出num-2,num-3,num-4...的情况;求n-1个骰子投出num-2的情况数的时候,需要递归求n-2个骰子投出num-3,num-4...的情况,这里看到会有重复求解的过程,因此为了优化算法,这里采用动态规划技术,以减少不必要的重复求解过程。使用HashMap<String,Double>来存储已经计算好的情况数。这里String作为键,用以标记“x个骰子投出y”,值Double为情况数。这里Double我本来用的是Integer,结果计算精度出现问题,后来用Long,还是显示有些测试精度存在问题,索性改成Double,就Accepted了。
PS:刚才又试了一下,Double和Long都好使,Integer会出现精度问题
Java算法实现
public class Solution {
/**
* @param n an integer
* @return a list of Map.Entry<sum, probability>
*/
public List<Map.Entry<Integer, Double>> dicesSum(int n) {
// Write your code here
// Ps. new AbstractMap.SimpleEntry<Integer, Double>(sum, pro)
// to create the pair
List<Map.Entry<Integer, Double>>list=new ArrayList<Map.Entry<Integer,Double>>(5*n+1);
Double pro=0.0;
double total=Math.pow(6, n);
double conditions=0; //刚开始我用的int,发现计算结果又精度问题,改成long还是有精度问题,最后改成double就没问题了
//但严格来说,情况数应该是整数,是没问题的,计算过程中没有出现溢出的情况,total已经是double了,
//难道 1/1.0 根1.0/1.0不一样?
HashMap<String,Double> hashMap=new HashMap<>();
for(int i=n;i<=6*n;i++){
pro=0.0;
conditions=findCombs(i, n,hashMap);
pro=conditions/total;
list.add(new AbstractMap.SimpleEntry<Integer, Double>(i,pro));
}
return list;
}
public static double findCombs(int num,int n,HashMap<String, Double>hashMap){
//为了简化计算,假设每个骰子最小值为0,最大值为5,共n个骰子
double total=0;
String key=String.valueOf(num)+","+String.valueOf(n);
if(hashMap.containsKey(key)){
return hashMap.get(key);
}
if(num<=0){
if(n>=1)
total=0;
else
total=1;//0 个骰子得到0 是可以的
}
else{
//num >0
if(n<1){
total=0;
}
else if(n==1){
if(num>6){
total=0;
}
else{
total=1;
}
}
else{
int ceil=num<=6?num:6;
for(int i=1;i<=ceil;i++){
total+=findCombs(num-i, n-1,hashMap);
}
}
}
hashMap.put(key, total);
return total;
}
}
LintCode2016年8月22日算法比赛----骰子求和的更多相关文章
- LintCode2016年8月22日算法比赛----将数组重新排序以构造最小值
将数组重新排序以构造最小值 题目描述 给定一个整数数组,请将其重新排序,以构造最小值. 样例 给定[3,32,321],通过将数组重新排序,可构造6个可能性的数字: 3+32+321=332321 3 ...
- LintCode2016年8月22日算法比赛----克隆二叉树
克隆二叉树 题目描述 深度复制一个二叉树. 给定一个二叉树,返回一个它的克隆品. 样例 给定一个二叉树: 1 / \ 2 3 / \ 4 5 返回其相同结构相同数值的克隆二叉树: 1 / \ 2 3 ...
- LintCode2016年8月22日算法比赛----平面列表
平面列表 题目描述 给定一个列表,该列表中的每个要素要么是个列表,要么是整数.将其变成一个只包含整数的简单列表. 注意事项 如果给定的列表中的要素本身也是一个列表,那么它也可以包含列表. 样例 给定 ...
- LintCode2016年8月8日算法比赛----中序遍历和后序遍历构造二叉树
中序遍历和后序遍历构造二叉树 题目描述 根据中序遍历和后序遍历构造二叉树 注意事项 你可以假设树中不存在相同数值的节点 样例 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下 ...
- LintCode2016年8月8日算法比赛----子树
子树 题目描述 有两个不同大小的二叉树:T1有上百万的节点:T2有好几百的节点.请设计一种算法,判定T2是否为T1的子树. 注意事项 若 T1 中存在从节点 n 开始的子树与 T2 相同,我们称 T2 ...
- LintCode2016年8月8日算法比赛----等价二叉树
等价二叉树 题目描述 检查两棵二叉树是否等价.等价意思是说,首先两棵二叉树必须拥有相同的结构,并且每个对应位置上的节点上的数据相等. 样例 1 1 / \ / \ 2 2 and 2 2 / / 4 ...
- 12月22日《奥威Power-BI财务报表数据填报》腾讯课堂开课啦
一扇可以通向任何地方的“任意门”,是我们多少人幼时最梦寐以求的道具之一.即使到了现在,工作中的我们还会时不时有“世界那么大,我想去看看”的念头,或者在突然不想工作的时刻,幻想着自己的家门变成了“任意门 ...
- Autodesk 最新开发技术研讨会 -8月22日-Autodesk北京办公室
为了增进与广大中国地区Autodesk产品的二次开发人员的了解与互动,帮助中国地区的Autodesk产品二次开发人员了解Autodesk最新的二次开发技术动向,并获得Autodesk公司专业开发支持顾 ...
- 见见面、聊聊天 - 5月22日晚7点Meetup,三里屯绿树旁酒吧,畅谈云技术和应用
总是邮件.QQ什么的线上聊,让我们见面吧,不怕见光死,呵呵. 我和同事会先抛砖引玉,给大家介绍一下Autodesk几款最新的云技术和解决方案,然后大家就可畅所欲言,自由交流.来自五湖四海的人,为了 ...
随机推荐
- 多事实表 SQL实现和SSAS中MDX实现的差异
如图,资产负债视图是事实表,损益表也是事实表.都包含年.月.组织.账簿信息. SQL如何实现呢? 简单粗暴,事实事实表串事实表,Full Join select 损益视图.年 ,损益视图.年月 ,损益 ...
- 最新版chrome浏览器如何离线安装crx插件?(转载)
原文链接:https://newsn.net/say/chrome-crx-offline.html mac新版chrome开启离线插件安装 对于mac新版chrome,注意,大家一定要按照顺序来.m ...
- SQL语句02(连表查询)
---恢复内容开始--- sql1992sql分类 1.笛卡尔积 (表乘表) 例:select * from emp,dept; 2.等值连接 表的连接条件使用“=” 例:select * ...
- 20190418 CentOS7实用技能综合:系统安装 + WinScp客户端连接 + 防火墙端口号iptables + Nginx编译安装 + MySQL编译安装 + Redis编译安装 + MongoDB编译安装 + ActiveMQ/RocketMQ/RabbitMQ编译安装 + ...各类常用生产环境软件的编译安装
系统安装 + WinScp客户端连接 + 防火墙端口号iptables + Nginx编译安装 + MySQL编译安装 + Redis编译安装 + MongoDB编译安装 + ActiveMQ/Roc ...
- JS框架设计之对象扩展一种子模块
对象扩展 说完了,对象的创建(框架的命名空间的创建)以及如何解决多库之间的命名空间冲突问题之后,接下来,就是要扩展我们的对象,来对框架进行扩展,我们需要一种新功能,将新添加的功能整合到我们定义的对象中 ...
- Java程序员的面试经历和题库
最近打算换城市了,受不了北京的雾霾了,所以准备逃离啦.所以一直在面试中,整理了下最近遇到的一些面试题,供大家参考.其中会包含一些面试的小经验,如果您是面霸,希望能给予指导.自己不是大牛,如果您是大牛, ...
- struts2 基本流程
一.配置过程 1.在web.xml中配置过滤器 <filter> <filter-name>StrutsPrepareAndExecuteFilter</filter-n ...
- OpenJDK编译运行
获取OpenJDK源码有两种方式,其中一种是通过Mercurial代码版本管理工具从Repository中直接取得源码(Repository地址:http://hg.openjdk.java.net/ ...
- redis实战笔记(1)-第1章 初识Redis
第1章 初识Redis 注:本书在redis3.0版本的,比如redis3.0以后支持服务端集群.3.0之前只能客户端分片. 本章主要内容 1.Redis与其他软件的相同之处和不同之处 2.Re ...
- Spring @Transactional踩坑记
@Transactional踩坑记 总述 Spring在1.2引入@Transactional注解, 该注解的引入使得我们可以简单地通过在方法或者类上添加@Transactional注解,实现事务 ...