public static int[] makeRandomArray1(Random rand, int size, int randMin, int randMax) {
//参数合法性检查
Objects.requireNonNull(rand, "rand不可为空");
if (size < 0) {
throw new IllegalArgumentException("size必须大于0,size==" + size);
}
if (randMax < randMin) {
throw new IllegalArgumentException(String.format(
"max必须大于或等于min,randMin==%d,,randMax==%d",
randMin, randMax));
}
if (randMax - randMin + 1 < size) {
throw new IllegalArgumentException(String.format(
"[randMin,randMax]范围内不足size个数,size==%d, randMin==%d, randMax==%d",
size, randMin, randMax));
}
//算法核心部分
int[] randArray = new int[size];
Map<Integer, Integer> conversion = new HashMap<>();
for (int i = 0, upper = randMax - randMin + 1; i < size; i++, upper--) {
int key = rand.nextInt(upper);
int val = conversion.getOrDefault(key, key);
randArray[i] = val + randMin;
conversion.put(key, conversion.getOrDefault(upper - 1, upper - 1));
conversion.remove(upper - 1); //这一行只是为了节约内存,少了也不影响程序的正确性
}
return randArray;
}
要实现最差情况下时间复杂度为O(n)
的算法,算法的性能必须不能因为size
和randMin~randMax
的相对大小而导致冲突次数增多而到时多次重试,进而增加时间复杂度,但也不能为了保证时间复杂度而违反随机这一原则(即要保证概率均等)。
如果你不介意运行效率,只想保证程序的正确性和编码的简单明了,那么其实可以用仅仅一行代码来实现。
public static int[] makeRandomArray2(Random rand, int size, int randMin, int randMax) {
//省略参数合法性检查
return rand.ints(randMin, randMax + 1).distinct().limit(size).toArray();
}