洗牌算法——将排序数组打乱的算法

参考:【算法】打乱有序的算法——洗牌算法

排序算法已经很了解,但是还是第一次见到这种乱序算法。在游戏研发过程中,多少会遇到这样的需求, 在一堆数据中随机打乱后再分配出去,并且保证每个物品分配到每个人手上的概率都是1/n。这个是比较典型的洗牌算法。

最普通的洗牌算法:

利用一个额外数组B,在数组A中随机选择一个数,如果没有被选择过,就扔到B中,如果选择过了,就重新随机。时间复杂度O(n^2),空间复杂度O(n),不是很好。

优化的洗牌算法:

不用开辟额外数组,从数组的最后一个元素开始,生成一个随机数,然后跟前面的元素进行交换,这样就洗出来了一个元素,再去洗前面n-1个元素就可以了,而且由于元素已经被移动到了最后,所以不用担心又选中了一个出现过的元素。

void shuffle(int *a,int n){
    for(int i = n-1;i>=1;i--){
        srand(unsigned(time)(0));//生成的随机数种子系统运行时间有关,确保每次都不同
        swap(a[i],a[rand() % (i+1)])
    }
}

或者可以使用C++ std::random_shuffle()

    int a[] = { 1,2,3,4,5,6,7 };
    random_shuffle(a,a+7);
    for (int i = 0; i < 7; i++)	cout << a[i] << " ";

面试题:

给定一个长度为n的有序数组,要求将其完全打乱,每个元素在任何位置出现的概率均为1/n


版权声明:本文为qq_34269988原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。