不重复随机数列生成算法2-数组有效位置的最后一个元素移动到当前位置
2016-05-13 17:28
731 查看
假设n=4
第一轮,我们随机获得2时,我们不将2从数组中移除,而是将数组的最后一个元素移动到2的位置
这时数组变成了
第二轮我们对0-2取随机数,这时数组可用的最后一个元素位置已经变成了2,而不是3。假设这时取到随机数为1
我们再把下标为2的元素移动到下标1,这时数组变成了
以此类推,直到取出n个元素为止。
这个算法的优点是不需要用一个hashtable来存储已获取的数字,不需要反复尝试,也不用像上一个算法那样删除数组元素,要做的只是每次把数组有效位置的最后一个元素移动到当前位置就可以了,这样算法的复杂度就降低为O(n),速度大大提高。
经测试,在n=100000时,这个算法的用时仅为7ms。
下面给出这个算法的实现代码
下面是n等于1万,10万和100万时的测试数据,时间单位为毫秒。从测试数据看GetRandomSequence2的用时和n基本成正比,线性增长的,这个和理论上的算法复杂度O(n)也是一致的,另外两个算法则随着n的增大,用时超过了线性增长。在1百万时,我的算法比用hashtable的算法要快10倍以上。
第一轮,我们随机获得2时,我们不将2从数组中移除,而是将数组的最后一个元素移动到2的位置
这时数组变成了
第二轮我们对0-2取随机数,这时数组可用的最后一个元素位置已经变成了2,而不是3。假设这时取到随机数为1
我们再把下标为2的元素移动到下标1,这时数组变成了
以此类推,直到取出n个元素为止。
这个算法的优点是不需要用一个hashtable来存储已获取的数字,不需要反复尝试,也不用像上一个算法那样删除数组元素,要做的只是每次把数组有效位置的最后一个元素移动到当前位置就可以了,这样算法的复杂度就降低为O(n),速度大大提高。
经测试,在n=100000时,这个算法的用时仅为7ms。
下面给出这个算法的实现代码
///<summary>
///Designedbyeaglet
///</summary>
///<paramname="total"></param>
///<returns></returns>
publicstaticint[]GetRandomSequence2(inttotal)
{
int[]sequence=newint[total];
int[]output=newint[total];
for(inti=0;i<total;i++)
{
sequence[i]=i;
}
Randomrandom=newRandom();
intend=total-1;
for(inti=0;i<total;i++)
{
intnum=random.Next(0,end+1);
output[i]=sequence[num];
sequence[num]=sequence[end];
end--;
}
returnoutput;
}
下面是n等于1万,10万和100万时的测试数据,时间单位为毫秒。从测试数据看GetRandomSequence2的用时和n基本成正比,线性增长的,这个和理论上的算法复杂度O(n)也是一致的,另外两个算法则随着n的增大,用时超过了线性增长。在1百万时,我的算法比用hashtable的算法要快10倍以上。
10000 | 100000 | 1000000 | |
GetRandomSequence0 | 5 | 44 | 1075 |
GetRandomSequence1 | 11 | 1038 | 124205 |
GetRandomSequence2 | 1 | 7 | 82 |
相关文章推荐
- 算法08 之堆
- doT.js 模板引擎的使用
- Google《Android性能优化》学习笔记
- gridview自动排序示例分享-自动排序
- SQL类型转换以及自动在前面补0满足10位工号标示法
- 欢迎使用CSDN-markdown编辑器
- Android开机自动启动应用
- Java中equals和==的区别
- linux tomcat配置https
- css 直角三角形 特殊三角形 对话气泡
- 01.Boost库安装及编译调试
- DOS常用命令
- 算法07 之哈希表
- 导弹拦截系统
- poi动态生成word
- 构建高并发高可用的电商平台架构实践
- struts2中拦截器与过滤器之间的区别
- vi里怎样批量缩进
- String——string-to-integer-atoi
- CentOS 设置 Tomcat 开机自动启动