排序算法已经很了解,但是还是第一次见到这种乱序算法。在游戏研发过程中,多少会遇到这样的需求, 在一堆数据中随机打乱后再分配出去,并且保证每个物品分配到每个人手上的概率都是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