随机输入两个整数m和n,其中m < n,输出是0到n-1范围内的m个随机整数的有序列表,不允许重复。
方案一:使用随机数的想法,通过取模的方式来控制产生的随机数的范围,然后通过设置一个计数器的方式控制选取的随机数的个数。
void getrand(int m,int n)
{
for(int i = 0;i < n;i++)
{
if(bigrand()%(n-i)<m)
cout<<i;
m--;
}
}
int bigrand()
{
return RAND_MAX*rand()+rand();
}
方案二:使用C++标准模板库,使用set容器,利用set容器的自带排序的功能,但是使用set容器也有缺点,缺点就是空间开销较大。
void getsets(int m,int n)
{
set<int> S;
while(S.size()<m)
S.insert(bigrand()%n);
set<int>::iterator i;//迭代器
for(i = S.begin();i!=S.end();i++)
cout<<*i<<endl;
}
方案三:最初的想法是把n个元素的数组打乱之后输出,再仔细思考可以发现,将数组的前m个元素打乱顺序进行输出即可。
void getrands(int m,int n)
{
int i,j;
int *x = new int[n];
for(i = 0;i < n;i++)
x[i] = i;
for(i = 0;i < m;i++)
{
j = randint(i,n-1);
int temp = x[i];
x[i] = x[j];
x[j] = temp;
}
sort(x,x+m);
for(i = 0;i < m;i++)
cout<<x[i];
}
int randint(int u,int l)
{
return u + bigrand()%(l-u+1);
}
方案四:以上的方案在一种极端情况的时候会出现浪费很多随机数的情况,当m和n的取值十分接近的时候,取模操作找到满足要求的余数的概率机会变得很小,借助佛洛依德算法就可以很好解决这个问题。
void floydrand(int m,int n)
{
set<int> S;
set<int>::iterator i;
for(int j = n-m;j<n;j++)
{
int t = bigrand(j+1);
if(S.find(t)=S.end())
S.insert(t); // t is not in S
else
S.insert(j)
}
for(i = S.begin();i != S.end();i++)
cout << *i << endl;
}