读书人

生成不反复的随机整数算法分析

发布时间: 2012-09-06 10:37:01 作者: rapoo

生成不重复的随机整数算法分析

?

算法一:????????用一个List保存所有候选的整数,依次 生成一个随机索引(该索引的范围需要递减),返回该元素,并移除该索引对应的元素值。(缺点:该算法经测试大概1M 的整数范围需要用到约16M 的内存空间,所以对于 大数据范围,多线程且每个线程分别独立生成不重复的随机整数 的情况下不太适用。 优点:该算法的可读性最强;而且因为会移除返回的元素,所以占用的内存会动态逐渐减少。)所以此处没有给出代码示例。?算法二:????????用一个数组保存所有候选的整数,依次 生成一个随机索引(该索引的范围需要递减),返回该元素,并 将末尾元素赋值到索引位置 且将原末尾元素位置前一个元素作为新的末尾元素。(缺点:可读性比上面的算法弱一点;占用内存一直不变。 优点:该算法经测试大概 1M 的整数范围需要用到约 4M 的内存空间(因为一个int数据占用4个Byte),比上面的算法好一点;时间复杂度比较低。)代码示例:
package com.kangfuqiang.util;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * <pre>  * Title:不重复的随机整数类 * Description: 用于依次获取 [MIN,MAX] 范围内的不重复随机整数; * 使用说明:需要new一个该类的实例(传入min和max参数),然后 使用该实例 依次获得不重复的随机整数; *  * ps:1M 的整数范围时,该实例占用的相关内存约为 4M 。 *  * </pre> */public class NoRepeatRandomInt {    private static Logger log = LoggerFactory.getLogger(NoRepeatRandomInt.class);        /** 最小值(包含) */    public final int MIN;    /** 最大值(包含) */    public final int MAX;            /** 计数器,记录已经领取不重复的随机整数的次数 */    private int counter = 0;        /** 保存 [MIN,MAX] 范围内的所有整数*/    private int[] numArr ;           /**     * @param min     * @param max     * @exception IllegalArgumentException 如果 min > max,则抛出该异常     */    public NoRepeatRandomInt(int min, int max) {        if(min>max){            String str = String.format("构造器参数错误,最小值不能大于最大值!min:%s,max:%s", min, max);            log.error(str);            throw new IllegalArgumentException( str );        }        this.MIN = min;        this.MAX = max;        numArr = new int[this.getOriginalCnt()];        for(int i=0; i<numArr.length; i++){            numArr[i] = i + this.MIN;        }    }        /**     * 领取 下一个不重复的随机整数     * @return     * @exception RuntimeException 如果 领取次数 超过 总个数范围,将抛出运行时异常     */    public int next(){        if(this.getRemainCnt()<=0){            String str = String.format("领取次数 超过 总个数范围(%d个)!", this.getOriginalCnt());            log.error(str);            throw new RuntimeException(str);        }        int idx = (int)(Math.random() * this.getRemainCnt());        int ret = numArr[idx];        numArr[idx] = numArr[this.getRemainCnt()-1];        numArr[this.getRemainCnt()-1] = ret;         this.counter++;        return ret;    }        /** 获得原始个数 */    private int getOriginalCnt(){        return this.MAX - this.MIN + 1;    }        /** 获得剩余个数 */    private int getRemainCnt(){        return this.MAX - this.MIN + 1 - counter;    }}
???算法三:????????使用Set集合来保证或保存不重复的随机整数。 这种算法适合 (返回数目/ 范围数目)的值非常小 的情况,其他情况还是使用上面的两种算法比较好。?PS:网上还有一些其他的算法,但是大多时间复杂度比较高,空间复杂度也没有明显的好处。1、遍历 已返回的随机数 的集合,以保证不重复随机整数。2、初始化List后,随机排序一下(shuffle),然后依次返回。3、初始化数组后,数组随机调换位置,然后依次返回。?欢迎大家交流、指点、评论与回复

读书人网 >编程

热点推荐