《劍指Offer》60:n個骰子的點數

題目

把n個骰子扔在地上,所有骰子朝上一面的點數之和為S。輸入n,打印出S的所有可能的值出現的概率。

分析

直接法

假設骰子有face面,有n個骰子,那么總排列數就有face?個。(例如,有3個6面骰子,那么其總排列數為63=216個)。所有骰子的和最小值為n(假設骰子最小值為1),而和最大值為n * face(例如,有3個6面骰子,那么和最大值為18), 那么就有 (n * face - n + 1)個可能和值,那么新建長度為(n * face - n + 1)的一維數組進行統計不同S出現的次數。

然后骰子分別依次一個一個地投,并將其可能的值累加,最后將相應數組元素自增。

最后,遍歷數組,除以總排列數,得出結果。

該算法時間復雜度為O(face?),當n越大,運算時間越長。(n從12開始增大,等待時間就開始難以接受)空間復雜度為O(n * face)。

動態規劃

確定問題解的表達式。可將f(n, s)表示n個骰子點數的和為s的排列情況總數

確定狀態轉移方程。n個骰子點數和為s的種類數只與n-1個骰子的和有關。因為一個普通骰子有六個點數,那么第n個骰子可能出現1到6的點數。所以第n個骰子點數為1的話,f(n,s)=f(n-1,s-1),當第n個骰子點數為2的話,f(n,s)=f(n-1,s-2),…,依次類推。在n-1個骰子的基礎上,再增加一個骰子出現點數和為s的結果只有這6種情況!那么有:

f(n,s) = f(n-1,s-1) + f(n-1,s-2) + f(n-1,s-3) + f(n-1,s-4) + f(n-1,s-5) + f(n-1,s-6)

上面就是狀態轉移方程,已知初始階段的解為:當n=1時, f(1,1)=f(1,2)=f(1,3)=f(1,4)=f(1,5)=f(1,6)=1。

該算法時間復雜度為O(n2),空間復雜度為O(n2)。


以3個6面骰子為例,所用到dp[i][j]數組如下圖所示。

i\j0123456789101112131415161718
00000000000000000000
10111111000000000000
20012345654321000000
300013610152125272725211510631

放碼

一、直接法

import java.util.Arrays;public class SumOfNDices {public static int DICE_MAX_VALUE = 6;public double[] getProbability(int numOfDice) {if(numOfDice < 1) {throw new IllegalArgumentException();}int maxSum = DICE_MAX_VALUE * numOfDice;int[] sums = new int[maxSum - numOfDice + 1];Arrays.fill(sums, 0);setSums(numOfDice, sums);int total = (int)Math.pow(DICE_MAX_VALUE, numOfDice);return Arrays.stream(sums).mapToDouble((a)->(a * 1.0 / total)).toArray();}public void setSums(int numOfDice, int[] sums) {for(int i = 1; i <= DICE_MAX_VALUE; i++) {setSums(numOfDice, numOfDice - 1, i, sums);}}public void setSums(int numOfDice, int leftNumOfDice, int sum, int[] sums) {if(leftNumOfDice == 0) {sums[sum - numOfDice]++;}else {for(int i = 1; i <= DICE_MAX_VALUE; i++) {setSums(numOfDice, leftNumOfDice - 1, i + sum, sums);}}}}

二、動態規劃(二維數組)

public double[] getProbability2(int numOfDice) {if(numOfDice < 1) {throw new IllegalArgumentException();}int[][] dp = new int[numOfDice + 1][numOfDice * DICE_MAX_VALUE + 1];double[] result = new double[numOfDice * DICE_MAX_VALUE - numOfDice + 1];double total = Math.pow(DICE_MAX_VALUE, numOfDice);Arrays.fill(dp[1], 1, DICE_MAX_VALUE + 1, 1);for(int i = 1; i <= numOfDice; i++) {//如1, 2, 3, 4, 5, 6 for(int j = i; j <= DICE_MAX_VALUE * numOfDice; j++) {//n個6面骰子的和的可能值 :6, 7, 8, 9, ...  for(int k = 1; k <= DICE_MAX_VALUE; k++) {//f(n, s) = f(n - 1, s - 1) + f(n - 1, s - 2) + f(n - 1, s - 3) + ...  dp[i][j] += (j >= k ? dp[i - 1][j - k] : 0); // j >= k 預防數組越界 if(i == numOfDice) {result[j - i] = dp[i][j] / total;}}}}return result;
}

由于每個dp[i][j]只于i-1時刻的狀態有關,所以可以刪去一個維度,簡化算法。

三、動態規劃(一維數組)

  • 在上述解法的基礎上,刪去一個維度
  • 第二個循環從后往前遍歷,避免覆蓋
public double[] getProbability3(int numOfDice) {if(numOfDice < 1) {throw new IllegalArgumentException();}int[] dp = new int[numOfDice * DICE_MAX_VALUE + 1];double[] result = new double[numOfDice * DICE_MAX_VALUE - numOfDice + 1];double total = Math.pow(DICE_MAX_VALUE, numOfDice);for(int i = 1; i <= DICE_MAX_VALUE; i++) {dp[i] = 1;result[i - 1] = 1.0 / DICE_MAX_VALUE;}for(int i = 2; i <= numOfDice; i++) {for(int j = DICE_MAX_VALUE * numOfDice; j >= 1; j--) {int temp = 0;for(int k = 1; k <= DICE_MAX_VALUE; k++) {temp += (j >= k) ? dp[j - k] : 0;}dp[j] = temp;if(i == numOfDice && j >= numOfDice) {result[j - i] = dp[j] / total;}}}return result;
}

測試

import java.util.Arrays;import org.junit.Assert;
import org.junit.Test;public class SumOfNDicesTest {@Testpublic void test() {SumOfNDices sd = new SumOfNDices();double[] result = sd.getProbability(1);System.out.println(result.length);System.out.println(Arrays.toString(result));}@Testpublic void test2() {SumOfNDices sd = new SumOfNDices();double[] result = sd.getProbability(10);double[] result2 = sd.getProbability2(10);Assert.assertArrayEquals(result, result2, 1E-10);}@Testpublic void test3() {SumOfNDices sd = new SumOfNDices();double[] result = sd.getProbability(10);double[] result3 = sd.getProbability3(10);Assert.assertArrayEquals(result, result3, 1E-10);}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/445855.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/445855.shtml
英文地址,請注明出處:http://en.pswp.cn/news/445855.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

fastjson解析多層數據_怎么解析三層List json數據

注意這個json格式不對前后的 [ ] 應該要去掉。 (我不是說你缺少的結束符)FastJSON 隨意解決的事情。0, compile com.alibaba:fastjson:1.2.71&#xff0c;去這個網站 http://www.jsonschema2pojo.org/粘貼你的json字符串1.1 Source type:JSON1.2 Annotation style:NONE1.3 所有…

《劍指Offer》37:序列化二叉樹

題目 請實現兩個函數&#xff0c;分別用來序列化和反序列化二叉樹。 分析 我們清楚可以通過前序遍歷序列和中序遍歷序列創造出一棵二叉樹。因此&#xff0c;我們可以先把一棵二叉樹序列化成一個前序遍歷序列和一個中序遍歷序列&#xff0c;然后在反序列化時通過這兩種序列還…

c linux 判斷ip合法_shell 檢測ip的合法性與檢測網絡掩碼的合法性

有時我們需要檢測IP輸入的正確性與網絡掩碼的正確性&#xff0c;用shell腳本寫的&#xff1a;#驗證ip地址的正確性check_ip_format(){echo $1 | grep "^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}$" > /dev/nullif [ $? 1 ]; thenreturn 1elseaec…

《劍指Offer》38:字符串的排列

題目 輸入一個字符串&#xff0c;打印該字符中字符的所有排列。 例如&#xff0c;輸入字符串abc&#xff0c;則打印出由字符a、b、c所能排列出來的所有字符串有abc、acb、bac、bca、cab、cba 分析 把一個字符串看成由兩部分組成&#xff1a;第一部分是它的第一個字符&#…

含有js的英文單詞_JavaScript 常用單詞整理

JS單詞push :添加一個數組元素document &#xff1a;文檔pop &#xff1a;刪除最后一個數組元素console &#xff1a;控制臺shift &#xff1a;刪除第一個數組元素string &#xff1a;字符串Concat 組合數組undefined &#xff1a;未定義typeof &#xff1a;關鍵字join&#xf…

《劍指Offer》23:鏈表中環的入口節點

題目 若一個鏈表中包含環&#xff0c;如何找出的入口結點&#xff1f;如下圖鏈表中&#xff0c;環的入口節點的節點3。 分析 一快&#xff08;移兩節點&#xff09;一慢&#xff08;移一節點&#xff09;兩指針判斷鏈表是否存在環。算出環有幾個節點&#xff08;上一步的兩指…

mysql數據庫上機題_MYSQL數據庫練習題操作(select)大全

1、 查詢Student表中的所有記錄的Sname、Ssex和Class列。select sname,ssex,class fromstudent;2、查詢教師所有的單位即不重復的Depart列。select distinct depart fromteacher;3、 查詢Student表的所有記錄。select * fromstudent;4、 查詢Score表中成績在60到80之間的所有記…

Java中<? super T>和List<? extends T>的區別

Java中<? super T>和List<? extends T>的區別 <? extends T> 下面通配符聲明List<? extends Number> foo3的賦值式是合法的&#xff1a; List<? extends Number> foo3 new ArrayList<Number>(); // Number "extends" …

mysql書寫規則_每天10分鐘帶你學會MySQL(二)SQL語句的基本書寫規則

SQL語句時必須要遵守一些規則。這些規則都非常簡單&#xff0c;接下來就讓我們逐一認識一下吧。1&#xff0c;SQL語句以分號(;)結尾。■SQL語句要以分號(;)結 尾一條SQL語句可以描述一個數據庫操作。在RDBMS當中&#xff0c;SQL語句也是逐條執行的。眾所周知&#xff0c;我們在…

《劍指Offer》52:兩個鏈表的第一個公共節點

題目 輸入兩個鏈表&#xff0c;找出它們的第一個公共節點。 public static class ListNode{public int val;public ListNode next;public ListNode(int val) {this.val val;} }分析 首先遍歷兩鏈表的長度。在第二次遍歷的時候&#xff0c;在較長的鏈表上先走若干步&#xf…

mysql win 64_win10下裝mysql-5.7.18-winx64

步驟1官網下載地址&#xff1a;https://dev.mysql.com/downloads/mysql/選擇手動安裝版&#xff1a;解壓到D盤mysql文件夾下&#xff1a;比以往的版本里缺少了兩個.ini文件&#xff0c;直接copy過來&#xff0c;進行修改,my.ini&#xff1a;[client]port3306default-character-…

《劍指Offer》62:圓圈中最后剩下的數字(約瑟夫環)

題目 0,1,2…,n-1這n個數字排成一個圓圈&#xff0c;從數字0開始&#xff0c;每次從這圓圈你刪除第m個數字。求出這個圓圈里剩下的最后一個數字。 例如&#xff0c;0、1、2、3、4這5個數字組成一個圓圈&#xff0c;從數字0開始每次刪除第3個數字&#xff0c;則刪除的前4個數字…

mysql數據庫老是被鎖怎么解決_Mysql數據庫全局鎖是如何引起的,如何解決?

2019-01-08 回答樂觀鎖與悲觀鎖不同的是&#xff0c;它是一種邏輯上的鎖&#xff0c;而不需要數據庫提供鎖機制來支持當數據很重要&#xff0c;回滾或重試一次需要很大的開銷時&#xff0c;需要保證操作的acid性質&#xff0c;此時應該采用悲觀鎖而當數據對即時的一致性要求不高…

我們邊吃曲奇邊聊——Cookie與Session那些事

Cookie與Session分別是什么&#xff1f; HTTP Cookie&#xff08;也叫 Web Cookie 或瀏覽器 Cookie&#xff09;是服務器發送到用戶瀏覽器并保存在本地的一小塊數據&#xff0c;它會在瀏覽器下次向同一服務器再發起請求時被攜帶并發送到服務器上。 通常&#xff0c;它用于告知…

mysql 不能添加外鍵 1215_MySQL錯誤1215:無法添加外鍵約束

我正在嘗試將新模式轉發工程到我的數據庫服務器上&#xff0c;但是我不知道為什么會收到此錯誤。我試圖在這里搜索答案&#xff0c;但是我發現的所有內容都說是將db引擎設置為Innodb或確保要用作外鍵的鍵是它們自己表中的主鍵。如果我沒記錯的話&#xff0c;我都做過這兩件事。…

JMH初體驗

什么是JMH JMH是 Java Microbenchmark Harness 的縮寫。中文意思大致是 “JAVA 微基準測試套件”。 基準測試是指通過設計科學的測試方法、測試工具和測試系統&#xff0c;實現對一類測試對象的某項性能指標進行定量的和可對比的測試。——百度百科 為什么要使用 JMH 基準測試…

java map取第一個元素_Java Set接口 Map 與枚舉

Set接口概述一個不包含重復元素的 collection。更確切地講&#xff0c;set 不包含滿足 e1.equals(e2) 的元素對 e1 和 e2&#xff0c;并且最多包含一個 null 元素特點Set接口是無序的 Set 是繼承于Collection的接口。它是一個不允許有重復元素的集合。Set可以存儲null值,但是nu…

Python中yield簡單用法

Python中yield簡單用法 你或許知道帶有yield的函數在Python中被稱之為generator&#xff0c;那何為 generator&#xff1f; 我們暫時拋開generator&#xff0c;先從一個常見編程題目開始&#xff0c;循序漸進了解yield的概念。 生成Fibonacci數列 Fibonacci數列是一個經典遞…

js 用下標獲取map值_js map方法處理返回數據,獲取指定數據簡寫方法

map方法處理返回數據&#xff0c;獲取指定數據簡寫方法前言后端返回數據為數組列表時&#xff0c;通常比較全面&#xff0c;包含了很多不需要的數據&#xff0c;可以通過 map 方法處理返回數據&#xff0c;篩選出想要的數據例如// 返回數據res [{id: 1,name: zhangsan,age: 16…

《Python Cookbook 3rd》筆記匯總

文章目錄一、數據結構二、字符串和文本三、數字、日期和時間四、迭代器與生成器五、文件與IO一、數據結構 標題關鍵詞1.1&#xff1a;拆分序列后賦值給多個變量可迭代對象、拆分賦值1.2&#xff1a;拆分任意長可迭代對象后賦值給多個變量可迭代對象、拆分賦值、星號表達式1.3&…