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灯, 水草

请输入看板名称,例如:Gossiping 或 站内搜寻

TOP