近期项目中须要生成N个不相等的随机数。实现的时候。赶工期,又有项目中N非常小(0-100)直接谢了一个最直观的方法:
public static List<Integer> randomSet(int num,int threshold){ Random random = new Random();
if(num > threshold) return null; Set<Integer> randomset = new HashSet<Integer>();
while(randomset.size() < num)
randomset.add(random.nextInt(threshold));
List<Integer> result = new ArrayList<Integer>();
result.addAll(randomset); return result ;
}
仅仅要是依据HashSet 的来去重,到达不相等的随机数,可是当num比較大。或者num 比較接近threshold 的时候。这个时候平均期望比較大num*threshold*lognum 的复杂度
其它类似的方法还有比方使用一个数组来标记某个数字是否已经标记到。复杂度同上
以下主要讲两个复杂度分别为num 和 threshold 的方法:
方法 1 : 置乱(shuffle)。代码例如以下:
public static List<Integer> random_shuffle(int num,int thresold){ Random rd = new Random();
List<Integer> result = new ArrayList<Integer>(thresold);
for(int i = 0 ;i < thresold ;i++)
result.add(i+1);
for(int i = thresold; i > 0;i--)
swap(result,i-1,rd.nextInt(thresold)); return result.subList(0, num);
}
将一个存有thresold 的数组,随机打乱顺序,然后返回前面num 个就可以。也能够直接使用Collections.shuffle(list)方法。看源代码可知,shuffle的算法也是如此。时间复杂度为threshold
方法 2 使用两个数组一个数组result 用来存结果 。target用来存1到threshold 个数,每次从去一个小于threshold的随机数 r,然后从target 中取出放到result 中,同一时候,target 中交换r 和threshold-1的数。同一时候threshold--。这样保证这个数字以后再也不会取到。
代码例如以下:
public static List<Integer> random_2(int num , int thresold){
Random rd = new Random();
List<Integer> target = new ArrayList<Integer>(thresold);
for(int i = 0 ;i < thresold ;i++)
target.add(i+1);
List<Integer> result = new ArrayList<Integer>(); for(int i = 0 ; i < num ;i++){
int r = rd.nextInt(thresold);
result.add(target.get(r));
swap(target, r, thresold-1);
thresold--;
} return result; }