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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值