题目:《程序员面试金典(第5版)》P332
编写一个函数,洗一副牌。要求做到完美洗牌,换言之,这副牌52! 种排列组合出现的概率相同。假设给定一个完美的随机数发生器。
提示:问题实际上等价为彻底打乱某个数组。
方法一:该方法和“蓄水池抽样算法”有类似之处。
void Swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
}
bool shuffleArrayInteratively(int* a,int len)
{
if(a==nullptr || len<=0)
return false;
for(int i=1;i<len;i++)
{
//PerfectRand()的作用是随机生成一个大于等于0、小于等于i的整数,由出题者提供
int randnum = PerfectRand(i);
Swap(a[randnum],a[i]);
}
return true;
}
方法二(更加简单明了):已随机序列从右向左扩大,未随机序列中随机选一个,与未随机序列的尾元素交换。
若要解决“从n个数中随机选出m个数”这个问题,则方法二中数组最后的m个数,就是随机选出的m个数。
bool shuffleArrayInteratively2(int* a,int len)
{
if(a==nullptr || len<=0)
return false;
for(int i=len-1;i>0;i--)
{
//PerfectRand()的作用是随机生成一个大于等于0、小于等于i的整数,由出题者提供
int randnum = PerfectRand(i);
swap(a[randnum],a[i]);
}
return true;
}