洗牌
今天从 svn 中取下一个同事的代码,浏览了一下。其中一段是关于洗牌的。感觉实现的很乱,算法也没有选好。自己重新写了一个。
因为国庆的缘故,负责这块代码的同事提前回家了。我只好自己读代码实现。看完后,发现旧的实现是这样的:对于 N 张牌,每次随机抽出一张来,检查这张牌是否抽过。如果被抽取过,就重复抽取过程,直到不重复。然后记录下抽取的牌的位置。重复这个过程,直到得到一个随机序列。最后用这个序列将原始排列打乱。
这个方案给我的第一感觉并不好,因为当 N 较大时,最后需要重复抽取多次才可以成功。我估算了整个的时间复杂度大约是 O(N^2)
当然,洗牌这件事情可以有许多算法来解决。我重新写了一个,采用了最简单实现的方案。
新的方案是从牌套里随机找到两个位置,将其位置的牌交换。重复若干次后,便可以将牌洗乱。这里最关键的是需要找到一个合适的重复次数。
这个问题首先需要定义什么叫作“洗乱”。
我随便给出了一个定义:在洗牌过程中,任意一张牌不被抽到交换的概率小于 1/1000 。(这个定义不太符合直观感觉,这个下面会讨论)
简单的列出方程:( (n-2)/n ) ^ m <=1/1000 得到 m >= -3* ln 10 / ln (1-2/n)
对于 52 张牌,大约是 176 次。
之后,另一个同事给了我另一个方案。产生 N 个不易发生碰撞的随机数,比如 (0,1) 的浮点数,或是 [0,4G) 的整数。将这些数字排序,则可以得到一个被打乱次序的序列。
这个方案看起来更好,因为更接近洗乱牌的目的。我重新给一个“洗乱”的定义:每张牌在每个位置出现的概率相同。
反过来,我想知道前面我给出的交换法洗牌有多接近它。
要得到严格的数学分析似乎很困难。偷懒 google 了一下,原来好多人研究过类似问题了。看这里:
http://mathworld.wolfram.com/Shuffle.html
从这个链接找过去,有一篇论文 。它讨论了另一种类似的洗牌方法,即第一次把第一张和随机一张牌交换,第二次把第二张和随机一张牌交换…… 重复做 N 次。
当 N 大于等于 18 时,用这个方法洗牌后,居然恒等排列(identity permutation)是最有可能出现的。(所谓恒等排列大概是指第 n 张排在第 n 个位置)。论文太长没精力读,不过这个结论还真是让人惊奇啊。
Comments
Posted by: 张斯禹 | (47) March 21, 2017 10:50 PM
Posted by: LYJ | (46) October 13, 2014 11:59 AM
Posted by: Seeker | (45) June 25, 2014 11:52 AM
Posted by: leokan | (44) January 24, 2011 11:05 AM
Posted by: zhangfaen | (43) September 23, 2010 12:03 AM
Posted by: Anonymous | (42) July 26, 2008 07:58 PM
Posted by: 玉米 | (41) October 24, 2007 09:45 AM
Posted by: 玉米 | (40) October 24, 2007 09:38 AM
Posted by: Cloud | (39) October 11, 2007 07:54 PM
Posted by: atyuwen | (38) October 11, 2007 07:05 PM
Posted by: atyuwen | (37) October 11, 2007 06:53 PM
Posted by: Anonymous | (36) October 10, 2007 10:01 AM
Posted by: 枫之羽 | (35) October 9, 2007 10:30 PM
Posted by: 极光炫影 | (34) October 8, 2007 01:23 PM
Posted by: 安德尔斯 | (33) October 6, 2007 09:27 PM
Posted by: 星染流云 | (32) October 6, 2007 01:05 PM
Posted by: Anonymous | (31) October 5, 2007 02:26 PM
Posted by: housisong | (30) October 4, 2007 04:46 PM
Posted by: Anonymous | (29) October 4, 2007 01:23 AM
Posted by: Anonymous | (28) October 4, 2007 12:44 AM
Posted by: 尉迟方 | (27) October 3, 2007 03:25 PM
Posted by: Anonymous | (26) October 3, 2007 02:04 PM
Posted by: Cloud | (25) October 2, 2007 11:14 PM
Posted by: Anonymous | (24) October 2, 2007 10:49 PM
Posted by: Anonymous | (23) October 2, 2007 09:53 PM
Posted by: phoolimin | (22) October 2, 2007 08:05 PM
Posted by: Anonymous | (21) October 2, 2007 03:46 PM
Posted by: 空心苹果 | (20) October 2, 2007 01:08 PM
Posted by: nothanks | (19) October 2, 2007 11:46 AM
Posted by: Anonymous | (18) October 2, 2007 10:59 AM
Posted by: sheep | (17) October 2, 2007 10:39 AM
Posted by: Anonymous | (16) October 2, 2007 05:20 AM
Posted by: Anonymous | (15) October 1, 2007 05:09 PM
Posted by: Anonymous | (14) October 1, 2007 05:08 PM
Posted by: Anonymous | (13) October 1, 2007 08:25 AM
Posted by: Atry | (12) October 1, 2007 02:45 AM
Posted by: Atry | (11) October 1, 2007 02:42 AM
Posted by: Atry | (10) October 1, 2007 02:39 AM
Posted by: Atry | (9) October 1, 2007 02:38 AM
Posted by: Atry | (8) October 1, 2007 02:30 AM
Posted by: Atry | (7) October 1, 2007 02:18 AM
Posted by: Atry | (6) October 1, 2007 01:41 AM
Posted by: 红色警戒 | (5) October 1, 2007 12:18 AM
Posted by: 红色警戒 | (4) September 30, 2007 11:37 PM
Posted by: Anonymous | (3) September 30, 2007 10:25 PM
Posted by: 红色警戒 | (2) September 30, 2007 08:47 PM
Posted by: missdeer | (1) September 30, 2007 08:09 PM