900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Java 随机数之从指定数据范围内随机选取n个不重复的数据

Java 随机数之从指定数据范围内随机选取n个不重复的数据

时间:2021-10-24 06:52:50

相关推荐

Java 随机数之从指定数据范围内随机选取n个不重复的数据

Java 随机数之从指定数据范围内随机选取n个不重复的数据

一、简述

记--从指定数据范围内随机选取n个不重复的数据,如从1~100中随机选取10个数据。

二、效果

三、工程结构

四、源文件

import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.Scanner;import java.lang.Integer;public class RandomTest {static List<Integer> mBaseList = null;//从[minVal, topVal]范围中选出cnt个不重复的数据public static List<Integer> genUniqueRandomVal(int minVal, int topVal, int cnt){int index;int size = topVal-minVal+1;if (minVal >= topVal){return null;}if (cnt>size){return null;}if (null == mBaseList){mBaseList = new ArrayList<Integer>();}//初始化基本数据集合mBaseList.clear();for (int i = minVal; i <= topVal; i++){mBaseList.add(i);}List<Integer> uniqueValList = new ArrayList<Integer>();//无重复的数据集合Random random = new Random();for (; cnt > 0;){index = random.nextInt(size);//范围[0, size)uniqueValList.add(mBaseList.get(index));//添加到数据集合mBaseList.remove(index);//基本数据集合移除已经加到uniqueValList的数据,这样子就不会重复cnt--;size--;}return uniqueValList;}public static void main(String[] args) {System.out.println("Please input min,max,count:");Scanner scan = new Scanner(System.in);//从输入流中获取三个数值int min = Integer.parseInt(scan.next());int max = 0;int cnt = 0;if(scan.hasNext()){max = Integer.parseInt(scan.next());if(scan.hasNext()){cnt = Integer.parseInt(scan.next());List<Integer> list = RandomTest.genUniqueRandomVal(min, max, cnt);for(Integer i : list) {//遍历打印得到的数据集合System.out.print(i+" ");}}}System.out.println("\nFinish.");}}

五、分析

指定范围内的随机数是会有重复的可能,并且小范围多次随机时重复率很高,为了快速生成不重复的随机数,我们需要保证每次得到的随机数是不一样的。如果生成的随机数是重复的,那么再生成一次,直到不重复。这个方法是不可取的,当选取数很接近数据总数时候,重复率是非常大的,如1~100中随机选取99不同的数时,可能需要生成次数远远大于99次,需要消耗很长时间或者几乎不能生成;因此我们采取以下方式:产生的随机数当作是索引,索引对应数据范围的一个数据,每次生成一个随机数就减少一个数据,并且下次随机数生成范围也相应减小,这样需要n个随机数时我们只需要生成n次即可。

如数据源是1 2 3 4 5 6 7 8 9 10 (基本数据集合)

第1次产生随机数范围是1到10,假设第1次产生的随机数是5,把5当作是索引,在基本数据集合中取第5个,并将5移除。

此时数据源变为 1 2 3 4 6 7 8 9 10

第2次产生随机数范围是1到9,假设第2次产生的随机数是8,把8当作是索引,在基本数据集合中取第8个,并将9移除

此时数据源变为 1 2 3 4 6 7 8 10

第3次产生随机数范围是1到8,假设第3次产生的随机数是6,把6当作是索引,在基本数据集合中取第6个,并将7移除

此时数据源变为 1 2 3 4 6 8 10

......

以此类推,直到选取的数据个数等于指定的个数。

注:生成的随机数小于等于基本数据集合的数据个数。

六、附-C语言实现

#include <stdio.h>#include <stdlib.h>#include <time.h> //随机生成用到time做种子int INTVALID = -1;//当作是无效的 int* baseArrPtr = NULL;//基本数据数组 //从size大小的arrPtr集合中取第index个数据int take(int* arrPtr, int size, int index){int i, j;if (NULL == baseArrPtr){return -1;}for (i = 0, j = 0; i<size; i++){if (arrPtr[i] != INTVALID){if (j == index){j = arrPtr[i];arrPtr[i] = INTVALID;return j;}j++;}}return -1;}//从min到max范围内取cnt个数据并填充到arrint getUniqueRandomArr(int arr[], int cnt, int min, int max){int i, j;int randNum;//随机数 int baseSize = max - min + 1;int tmpSize = baseSize;INTVALID = min - 1;if (min >= max){return -1;}if (cnt>baseSize){return -2;}if (NULL != baseArrPtr){free(baseArrPtr);}//为基本数据数组分配空间 baseArrPtr = (int*)malloc(baseSize*sizeof(int));if (NULL == baseArrPtr){return -3;}//初始化基本数据数组 for (i = 0, j = min; i < baseSize; i++, j++){baseArrPtr[i] = j;}srand(time(0));//设置随机数种子 //rand()%num产生 0~num-1//rand产生范围数公式rand()%(m+1-n)+n;有效范围在 [n,m]for (i = 0; cnt>0; cnt--){randNum = rand() % tmpSize;//randNum的有效范围在 [0,baseSize-1]arr[i++] = take(baseArrPtr, baseSize, randNum);tmpSize--; }free(baseArrPtr);return i;}int main(int argc, char *argv[]){int i;int min;int max;int cnt;int arr[128] = { 0 };printf("Please input min, max, count:");scanf("%d %d %d", &min, &max, &cnt);getUniqueRandomArr(arr, cnt, min, max);for (i = 0; i<cnt; i++){printf("%d ", arr[i]);}printf("\nFinish.\n");//system("pause");return 0;}

效果:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。