取 最小值到最大值之间不重复的随机数(Random)问题
面试的时候遇到过同样类型的问题所以做下记录
我想到用两种方法去解决这个问题
方法一:用Set集合去重
这个方法比较简单好理解,当时面试的时候给的也是这种答案
Set集合有不重复数据的特性,一直循环得到不重复的数字,长度到指定不重复数据的个数时则停止。
/**
* @param minNum 最小数
* @param maxMum 最大数
* @param numRange 随机数个数
*
* */
public static Set<Integer> getSetRandom(int minNum ,int maxMum,int numRange){
if ( numRange <= 0 || numRange > (maxMum-minNum+1) || maxMum- minNum <0){
System.out.println("传入数字不正确");
return null;
}
//返回set集合
Set<Integer> result = new HashSet<>();
//循环次数
int forNum = 0;
//set集合等于不重复随机数个数时停止循环
while (result.size() !=numRange){
result.add(new Random().nextInt(maxMum-minNum+1)+minNum);
++forNum;
}
System.out.println("Set取值循环"+forNum+"次");
System.out.println(result);
return result;
}
方法二:用ArrayList集合实现
首先有个存放范围数字的集合(最小值到最大值的范围)
ArraList集合的数据是从下标0开始的,每个范围数字都有一个对应下标
以不重复随机数的个数作为循环次数(取多少个随机数循环多少次),每次循环用范围集合数据长度范围内的一个随机值,这个值对应的下标都有一个数字,删除这个下标对应的数字并取出放到另个一集合内(保证了下次取值不会重复),同样范围集合中数字少一,集合长度同样减一。
/**
* @param minNum 最小数
* @param maxMum 最大数
* @param numRange 随机数个数
*
* */
public static List<Integer> getDistinctRandom(int minNum ,int maxMum,int numRange){
if ( numRange <= 0 || numRange > (maxMum-minNum+1) || maxMum- minNum <0){
System.out.println("传入数字不正确");
return null;
}
// 返回的结果集合
List<Integer> result = new ArrayList<>();
//过滤的数据集合最小数到最大数的数字集合
List<Integer> list = new ArrayList();
for (int i = minNum ; i < maxMum+1 ; i++){
list.add(i);
}
//取出不重复的随机数
int forNum = 0;
for (int i = 0; i < numRange ; i++) {
int num = new Random().nextInt(list.size());
result.add(list.remove(num));
++forNum;
}
System.out.println("ArrayList取值循环"+forNum+"次");
System.out.println(result);
return result;
}
随机数取值两种方法也可以延伸为数据
两种的方法对比下:
(1)Set集合适用于大数据量,取值的个数(取不重复随机数的个数)小于取值数据个数一半(最小值到最大值范围数字)越小越好
因为你取值的个数大于数据个数的一半,越大重复的概率就越大,循环的次数必然增加
(2)ArrayList集合,因为需要定义一个范围的数据,从那个范围的数据内反复取值,小数据量不影响,大数据量的取值的个数大于范围数据个数的一半,可以建议使用,循环次数是取值数据的个数
————————————————————————————————
以上是我个人总结,有不对的地方欢迎留言指正,希望共同进步!谢谢!