问题如下:
现有n个不同的整数,如何从中随机选出m个不同的数。(m<=n)
思路:
一提到随机数函数,我们立即想到rand(),此函数使用方法如下:
要取得[a,b)的随机整数,使用 rand()%(b-a) + a;
要取得[a,b]的随机整数,使用 rand()%(b-a+1) + a;
要取得(a,b]的随机整数,使用 rand()%(b-a) +a +1;
通用公式:
a + rand()%n, 其中的 a 是起始值,n是整数的范围。
可是,rand函数本身并不能保证产生的随机数不重复。网上搜索了一下,最优方法是这样的:
1.从n个数中产生一个随机数
2.从剩下的 n-1 个数中产生下一个随机数
3.从剩下的 n-2个数中产生下一个随机数
...,如此产生m个不同的随机数。
由于每次操作的集合不包括之前产生的随机数,所以不会发生重复问题。代码实现如下:
int a[100]; for(i = 0; i < 100; ++i) a[i] = i; for(i = 99; i > 0; --i) swap(a[i], a[rand()%(i+1)]);
参考文章:
Fisher–Yates shuffle
To shuffle an array a of n elements (indices 0..n-1): for i from n − 1 downto 1 do j ← random integer such that 0 ≤ j ≤ i exchange a[j] and a[i]
后记:
随机数这个问题很大,以后可能还要添加内容。下面先贴下swap的3种实现:
void swap(int &a, int &b) { int tmp = a; a = b; b = tmp; } void swap(int &a, int &b) { a = a + b; b = a - b; a = a - b; } void swap(int &a, int &b) { a ^= b; b ^= a; a ^= b; }