原文出处:http://blog.sina.com.cn/s/blog_57de62c00100ltak.html
如何产生不重复的随机数?最容易想到的方法,是逐个产生这些随机数,每产生一个,都跟前面的随机
数比较,如果重复,就重新产生。这是个很笨的方法,且比较次数呈线性增长,越往后次数越多。其实这些
比较是多余的,完全可以不进行比较,只要反过来,按顺序产生这些数,但随机产生它们的位置。例如下
面产生100个100以内不重复随机数的代码:
int a[100];
for(i=0; i<=99; ++i) a[i]=i;
for(i=99; i>=1; --i) swap(a[i], a[rand()%i]);
上面这段代码只需要遍历一次就可以产生这100个不重复的随机数,它是如何做到的呢?首先第二行按顺
序用0到99填满整个数组;第三行,是随机产生从0到m-2个数组下标,把这个下标的元素值跟m-1下标的元
素值交换,一直进行到下标为1的元素。因此它只需要遍历一次就能产生全部的随机数。
int a[100]={0};
int i, m;
for(i=1; i<=99; ++i)
{
}
这段代码也是随机产生位置,但它预先把整个数组初始化为0,然后随机产生其中一个位置,如果该元素
值为0,表示这个位置还没有被使用过,就把i赋予它;否则,就重新随机产生另一个位置,直到整个数组
被填满。这个方法,越到后面,遇到已使用过的元素的可能性越高,重复次数就越多,这是不及第一个方
法的地方,但总的来说,效率还是不错的。
===================================================================================
1.产生一个随机数(从0到32767)
2.产生从m到n的随机数(包括m,不包括n)
==================================================================================
问题的来由 - "随机取m个数(在1到n的范围之内),(m <= n),要求m个数没有重复。有没有
什么好的算法,时间复杂度和空间复杂度都很好"
----------------------------------------------------------------
方案一:
取随机数可以用C++标准的rand,至于M个不重复,你可以用std::set来解决,把取道的随机数
插入到set里面,set的size() == m就可以了, 具体可以这样:
#include <set>
#include <stdlib.h>
int main()
{
}
由于set底层实现是红黑树,插入复杂度是对数级的^_^
----------------------------------------------------------------
方案二:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main (){
}
1. C++标准函数库提供一随机数生成器rand,返回0-RAND_MAX之间均匀分布的伪随机整数。 RAND_MAX
2. C++中另一函数srand(),可以指定不同的数(无符号整数变元)为种子。但是如果种子相同,伪
3. 比较理想的是用变化的数,比如时间来作为随机数生成器的种子。
4. 但, srand()并不是说使随机数都不一样,它只是使取随机数的种子随着时间而改变:)
===============================================================================
生成无重复的随机数,注意,是不重复的序列.
一.牺牲时间为代价
二.牺牲空间为代价
for i ← 1 to length[a]
do j ← random() // 随机产生一个a数组的下标
exchange a[i]←→a[j] // 交换a[i]与a[j]
当范围数组与目标数组的大小非常接近时,上述算法非常有效,建议采用.
(2)问题的最终解决.
伪码算法如下: