获取1-n之间不重复随机数的几种方法
最近接到一个小任务,给定一个整数n,获取1-n之间不重复的n个随机数。于是我便动手写了写,发现实现不难,但是一般时间复杂度都比较高,于是思考了一下,又看了其他一些人的思路,最终总结了以下三种实现方式。
第一种:最常规的方式,flag标志位判重,这种方式是最容易想到的,也是时间复杂度很高的一种.
package com.wl.test3;
import java.util.Scanner;
/**
* 给定一个整数n,生成1-n之间不同的n个随机整数
* Math.random()-->[0.0,1.0)
* @author Administrator
*
*/
public class TestRandom {
public static void getRandom(int n) {
/** 生成的n个随机数数组 */
int[] numbers = new int[n];
/** 随机数的个数 */
int count = 0;
while (count < n) {
/** 生成[1,n+1)之间的随机整数 */
int number = (int) (Math.random() * n + 1);
/** 标志位,用于判断生成的随机整数是否已经存在相同的 */
boolean flag = true;
/** 第count个整数与前边生成的count-1个数进行比较 */
for (int i = 0; i < count; i++) {
/** 若存在相同的,标志位置false,跳出循环,重新生成一个整数 */
if (number == numbers[i]) {
flag = false;
break;
}
}
if (flag) {
numbers[count] = number;
count++;
}
}
for (int num : numbers) {
System.out.println(num);
}
}
@SuppressWarnings("resource")
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("请输入一个整数n:");
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
long start =System.currentTimeMillis();
getRandom(n);
long end =System.currentTimeMillis();
System.out.println("共耗时:"+(end-start)+"毫秒");
}
}
第二种:使用set集合判重,运行时间上要比第一种快些,但是因为set底层实现本身时间复杂度就要o(n),所以使用起来也并不是很理想。
package com.wl.test3;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class TestRandom2 {
public static void getRandom(int n,Set set) {
int size=0;
while(size set=new HashSet();
long start=System.currentTimeMillis();
getRandom(n,set);
long end=System.currentTimeMillis();
System.out.println("运行时间:"+(end-start)+"毫秒");
}
}
第三种:使用两个数组,一个存储有序的可能生成的所有的随机数数值,一个存放最终生成的随机数。生成的随机数不再直接取,而是作为数组索引,在数组生成的随机索引的位置取相应元素,这样也能保证取得元素是随机的,而且生成的随机数范围逐渐减小,可以避免出现重复值,这种是时间复杂度最低的一种。
package com.wl.test3;
import java.util.Scanner;
public class TestRandom11 {
public static void dis(int n) {
/**存放1-n元素的数组,便于随机选取*/
int[] b =new int[n];
/**存放生成的随机数的数组*/
int[] a=new int[n];
/**生成的随机数的上界,即获取数组索引的上界*/
int max=n;
/**生成元素为1-n的数组*/
for(int i=0;i
比较:
1.生成100个随机数,数量不大,因此三种方式的运行时间也差别不大,大概有在2,3毫秒左右。
2.生成1000个随机数,数量增加,也不是很大时,第一二种方式,差别不大,大概分别是19,22毫秒左右,而第三种则有明显提升,13毫秒左右。
3.生成10000个随机数,数量比较大时,差别很大,第一种耗时617毫秒,第二种耗时109毫秒,第三种则耗时64毫秒,此时第一种方式可以很明显的看出速度很慢。
总结一下,在生成大量的随机数时,还是推荐使用第三种方式。