我正在处理扑克牌洗牌问题,并为此找到了两种解决方案。
目标是将存储在阵列中的所有52张扑克牌洗牌为Card对象。 Card类具有与之关联的id和名称。
现在,一种方法是使用for循环迭代,然后在临时卡对象持有者和随机数生成器的帮助下,我们可以交换两个对象。这一直持续到我们达到一半的牌。
另一种方法是使用随机生成器编号实现可比较的重写比较方法,因此每次调用方法时都会得到随机响应。
你认为哪种方式更好?
答案 0 :(得分:1)
你应该不通过使用返回随机结果的比较器进行排序来做到这一点,因为那些随机结果可能彼此不一致(例如,说a< b< c< a< a),而这实际上可能导致你得到的订单分布远非均匀。参见例如this demonstration by Mike Bostock。此外,它需要更长的时间,而不是重要的是洗改52个物体。
standard way to do it 确实涉及一个循环,但你的描述听起来很奇怪,我怀疑你的想法可能也不会产生理想的结果。 (如果更新问题以更清楚地说明"迭代使用for循环"方法是什么意思,我会更新它。)
(是通过排序获得良好改组的方法:将每个元素与随机数对齐 - 例如,0..1范围内的随机浮点数 - 和 - 然后使用该数字作为关键字进行排序。但这比Fisher-Yates慢,需要额外的内存。在低级语言中,它通常也需要更多的代码;在更高级别的语言中,它可能更简单;我猜这个对于Java来说,它最终是平等的。)
[已编辑添加:]正如Louis Wasserman在评论中非常明智地说,当您的语言标准库具有现成的功能时,您通常应该使用它。除非您正在执行此操作,例如,需要您找到并实施算法来解决问题的家庭作业。
答案 1 :(得分:0)
首先,你所描述的比较器不起作用。有关此问题的更多信息here。 TLDR:比较必须是可重现的,因此,如果比较器在a
与b
进行比较时说明b
小于a
,那么返回“更大”,而不是随机值。 Comparable
也一样。
如果我是你,我宁愿使用Collections#shuffle
method,它“使用默认的随机来源随机置换指定列表。所有排列都以大致相等的可能性发生”。依靠某人的代码总是更好,然后编写自己的代码,特别是如果它在标准库中。