java 板


LINE

有朋友寫信問我有關這個程式的問題 我想說乾脆好好在這裡幫大家說明一下 希望有幫助 有需要的話可以配合程式看 (相信我,解釋程式不能當面說明真的很難說得清楚,我盡力啦) 假設我們現在要在1~10之中取出二個不重複的亂數 程式執行過程如下 第一回合執行前 [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] //陣列索引 1 2 3 4 5 6 7 8 9 10 //陣列內容 假設第一回合從[0]~[9]之中取到[5]這個位置好了 接著便把[0]和[5]的“內容“交換 (打*處) [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] //陣列索引 6 2 3 4 5 1 7 8 9 10 //陣列內容 * * 完畢後你可以想成[0]是用來放答案的地方 所以下次取亂數的時候不再考慮[0]這個位置,也就是說6這個數字已經取過不再考慮 這也是為甚麼第二回合我們只取[1]~[9](不去碰答案區) 第二回合執行前 [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] //陣列索引 6 2 3 4 5 1 7 8 9 10 //陣列內容 接著第二回我們便從[1]~[9]之中來取 假設又取到[5]這個位置好了(巧合嘛^^,你也可以自行換別的數字) 接著便把[1]和[5]的“內容“交換 (記得我剛說[0]是答案區,我們不去動它的) [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] //陣列索引 6 1 3 4 5 2 7 8 9 10 //陣列內容 * * 這時候你可以想成[0]和[1]是用來放答案的地方 所以下次取亂數的時候不再考慮[0]和[1]這二個位置 也就是說6和1這二個數字已經取過不再考慮 這也是為甚麼第三回合(如果有的話)我們只取[2]~[9] 所以這個例子裡最後取出來的亂數是6, 1 好,接著來思考一下機率問題 首先第一回合取亂數時是不是1~10每一個數字被取到的機率是一樣的? ...答案是肯定的(機率為1/10),所以第一回合OK 那第二回合呢? 記得我們的問題是...取“不重複“的亂數 所以第一回合取到的6當然就不考慮啦 也就是說在第二回我們要從1,2,3,4,5,7,8,9,10這“九“個數字中取出一個亂數(不包含6) 因為[0]已經是答案區啦 而我第二回合只取[1]~[9] 現在你觀察一下第二回開始前[1]~[9]的內容 是不是剛好就是1,2,3,4,5,7,8,9,10這九個數字 (要想一下喔,這可不是巧合^^) 所以第二回合中這九的數字被選到的機率也是一樣的(機率為1/9) 請注意 雖然1/10和1/9好像機率不同,但別忘了這已經是第二回合囉,只剩下九個數字嘛 (而且要第一回合槓龜的人才有這榮幸出現在第二回合阿) 結論是每一個數字在這二回合的過程中被取到的機率是 (1/10)+(9/10*1/9) = 1/5 回想一下我們要解的問題你會發現 10個數字裡面任挑二個不重複的數字 每一個數字被挑到的機率本來就就是1/5囉(請參考機率課本) 希望這樣的說明真的有清楚了 最後我想說 我知道一般這個問題的解法都是 “把陣列打亂,然後取亂數“ 但有沒有想過 到底要打多少次才夠亂? 我提供的程式基本上從機率的角度出發 利用一些小技巧避免“把陣列打亂“這個動作 讓程式跑起來比較有效率一些 作為大家參考吧 ※ 引述《ninteen (小美)》之銘言: : ※ 引述《ninteen (小美)》之銘言: : : janyfor的方法是比較好的 : : 運算複雜度比較低 : : 不過所謂打亂陣列的地方可能要修改一下 : : 以下我提供程式碼 : : int Max = 46; //亂數的最大值 : : int[] numbers = new int[Max]; : : for (int i=0 ; i<Max ; i++) numbers[i]=i;//陣列初始化 : : int n = 6; //你需要的亂數個數 : : int pick, temp; : : for(int i=0 ; i<n ; i++){ : : pick = (int)(Math.random()*(Max-i) + i);//重點在這裡 : : //Swapping : : temp = numbers[pick]; : : numbers[pick] = numbers[i]; : : numbers[i] = temp; : : } : : //Show出亂數 : : for(int i=0 ; i<n ; i++) System.out.println(numbers[i]); : 這個程式確實會出現0 : 如果不想出現0 : 把for (int i=0 ; i<Max ; i++) number[i]=i; : 改成for (int i=0 ; i<Max ; i++) number[i]=i+1; 即可 : 至於Max-i這個地方是重點,不是我寫錯 : 基本精神是,取過的亂數不再取 : 也就是說 : 第一次取0~45,然後取出的亂數放到陣列的[0]的位置,一但放過去之後就不再動它 : 第二次取1~45,然後取出的亂數放到陣列的[1]的位置,一但放過去之後就不再動它 : 第三次取2~45,然後取出的亂數放到陣列的[2]的位置,一但放過去之後就不再動它 : 依此類推 : 希望這樣說明有清楚 : 原諒我不能畫圖很難說明 --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 24.17.240.114 ※ 編輯: ninteen 來自: 24.17.240.114 (12/11 17:17) ※ 編輯: ninteen 來自: 24.17.240.114 (12/11 17:18)
1F:推 nanie:好清楚的說明 .. 我只看出可以取出結果 XDD 沒看出機率相同 12/11 19:38
2F:推 howard666:GOOD! 12/12 21:20







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:BuyTogether 或 站內搜尋

TOP