Algorithm 洗牌算法之间的差异
假设我们要编写一个方法来生成一副洗牌。现在让它变得非常简单,不考虑西装,所以我们有52张卡片 一种算法是:Algorithm 洗牌算法之间的差异,algorithm,shuffle,array-algorithms,Algorithm,Shuffle,Array Algorithms,假设我们要编写一个方法来生成一副洗牌。现在让它变得非常简单,不考虑西装,所以我们有52张卡片 一种算法是: 填充一个包含52个元素的数组,第一个元素为1,第二个元素为2,依此类推 编写一个for循环,循环X次,在每次迭代中,选择两张随机卡并交换它们 X越大,随机洗牌的次数就越多 另一种算法: 像前面一样填充数组 编写一个for循环,循环26次,在每次迭代中选择两个随机数,并将这两个数放在另一个52元素数组的连续前端,该数组存储新选择的数 在每次迭代中,从原始阵列中移除添加到新阵列中的两张卡
- 填充一个包含52个元素的数组,第一个元素为1,第二个元素为2,依此类推
- 编写一个for循环,循环X次,在每次迭代中,选择两张随机卡并交换它们
- X越大,随机洗牌的次数就越多
- 像前面一样填充数组
- 编写一个for循环,循环26次,在每次迭代中选择两个随机数,并将这两个数放在另一个52元素数组的连续前端,该数组存储新选择的数
- 在每次迭代中,从原始阵列中移除添加到新阵列中的两张卡
Random r = new Random(DateTime.Now.Miliseconds);
string [] cards = new string[52]{"1","2",.....};
int [] temp = new int[52];
for(int i=0;i<52;i++)
{
temp[i]=r.Next();
}
Array.Sort(temp,cards);
Random r=new Random(DateTime.Now.毫秒);
string[]cards=新字符串[52]{“1”、“2”、…};
int[]temp=新int[52];
对于(int i=0;i你必须定义你所说的“更好”是什么意思。第一种算法的问题是,某些元素可能永远不会改变位置。例如,如果你从来没有随机获得过较低的数字,那么第一张牌将按顺序排列
第二种算法将使您获得更多的随机化。但是,如果您只运行一次,那么项目在其最终位置将可能是可预测的
我要么多次运行算法2,要么像洗真牌一样洗牌
1: Split the deck into two arrays of 26
2: Take the top card from one of the arrays at random and put it into a new array of size 52
3: Keep doing this until one array is empty, put the remaining cards of the other array into the size 52 array
4: Repeat
这将为您带来一个很好的随机化第二个算法似乎是一个由两个实现展开的算法。这种随机洗牌的特性是在所有可能的结果中选择一个均匀分布。大多数人会称之为“公平”或“完美”洗牌。如果您的随机数生成器提供无偏结果,则无需为额外的随机性重复该操作
第一个算法可能渐近地接近我不知道什么样的分布。我会出于各种原因避免它。主要是因为我不知道X需要多大才能产生一个好的洗牌,但我确信它超过52。除了simula之外,我想不出这个算法有什么好的应用洗牌不充分
第一种算法正在运行,这在某些情况下是有益的,但如果您想这样做,您可以修改第二种算法,使其以类似的方式运行。第一种算法产生高度偏差分布,因为它可能会使一些卡处于初始位置,并容易出现“双交换”问题(交换相同的两张卡两次,导致初始卡状态)
第二种算法是的展开版本,但有一个小例外:它不再是线性的,因为从列表中删除项本身就是线性操作,并且在每次迭代中都会执行,因此总体算法复杂度为O(n^2)
有效的版本如下:
在伪代码中(因为您没有提到选择的语言)
和python实现,以防万一:)
“更好”根据什么标准?这不取决于第一种算法中X
的值吗?第一种算法能够生成一个更随机的集,但第二种算法在运行时间和空间复杂度方面是固定的。如果X是26?或52?在这两种情况下,X与第二种算法相比如何?您仍然需要定义criteria:你说的“更好”是什么意思?“更好”应该更随机像下面提到的sh1一样,第二种算法是Fisher-Yates算法。只要他的代码忽略在一次迭代中两个随机数相同的实例(我没有写出完整的数学公式,但我认为概率仍然是一个均匀分布的随机数)。我看不出第二个算法如何能够执行双重交换。它将值从一个数组移动到另一个数组。这看起来像是一个模拟。正如注释上的Wikipedia文章所述,这种方法是O(n logn)及时,而Durstenfeld对Fisher-Yates的实施时间为O(n)。
for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]
import random
n = 52
arr = [i for i in range(1,n+1)]
for i in range(n-1, 1, -1):
elem_to_swap = random.randint(0, i)
arr[elem_to_swap], arr[i] = arr[i], arr[elem_to_swap]