算法--生成m个指定范围的不重复随机数的三种方法分析(Java实现)

Q题目

如何产生m个在0-N范围内的无重复的随机数(不包含N)

A解法

2.1 常见解法有两种:

1.间接获取--采用随机下标从已实例化的数组中取元素
2.直接获取随机数--然后一一排除

2.2 间接法逻辑分析

  • 第一步:将指定范围内的所有数循环放入数组arr中

  • 第二步:使用随机下标从该数组中取值,去过的值,赋值为-1

  • 第三步:每次取值时,根据取出来的值是否是 -1来判断该值是否已经取过

  • 第四步:取过,则重新取值,没取过,直接拿来用

2.3 直接发逻辑分析

给长度为m的数组arr,依次赋值,每次赋值前,都与前面已经赋值的数进行比较是否重复,若重复,则重复生成随机数赋值,若不存在,直接赋值。

2.4 两种方法实现代码如下

package 随机不重复数组;
//用于产生m个在0-N范围内的无重复的随机数(不包含N)

import java.util.Arrays;

public class Test1 {
    public static void main(String[] args) {
        //测试--产生20个在0-30范围内的无重复的随机数
        int num=20;
        int scope=30;//即取[0,19)中的整数

        //方法一测试
        int[] testArr=getRandomArrayByIndex(num, scope);
        System.out.println("方法一测试结果:"+Arrays.toString(testArr));

        //方法二测试
        int[] test2Arr=getRandomArrayByValue(num, scope);
        System.out.println("方法二测试结果:"+Arrays.toString(test2Arr));


    }

    //方法一:间接取值--实例化指定范围内所有值--再用随机下标求值
    //参数说明:num--无重复随机数的个数   scope--随机数所在范围(不包含scope)
    public static int[] getRandomArrayByIndex(int num,int scope){
        //1.获取scope范围内的所有数值,并存到数组中
        int[] randomArray=new int[scope];
        for(int i=0;i//2.从数组random中取数据,取过后的数改为-1 
        int[] numArray=new int[num];//存储num个随机数
        int i=0;
        while(iint index=(int)(Math.random()*scope);
            if(randomArray[index]!=-1){
                numArray[i]=randomArray[index];
                randomArray[index]=-1;
                i++;
            }
        }

        return numArray;
    }

    //方法二:for循环直接取值
    public static int[] getRandomArrayByValue(int num,int scope){
        //创建存储num个随机数的数据
        int[] numArray=new int[num];
        int lucky;//存生成的随机数

        //是否继续
        boolean isContinue=true;
        for(int i=0;ido {
                lucky=(int)(Math.random()*scope);//获得随机数

                //判断数组中是否已经存在了这个随机数
                //--存在返回true,重新生成随机数  --不存在,返回false,停止循环,将该值赋值给数组
                isContinue=isExistence(numArray, lucky);
            } while (isContinue);

            numArray[i]=lucky;
        }

        return numArray;
    }

    //方法二的辅助方法
    public static boolean isExistence(int[] numArray,int lucky){
        for (int i : numArray) {
            if(i==lucky){
                //存在返回true--生成新的随机数,直到随机数与放入数组numArray中的数不同为止
                return true;
            }
        }

        return false;
    }
}

测试多次结果

这里写图片描述

这里写图片描述

这里写图片描述

方法优劣:

方法一(间接法):比较占内存,每次都需要将所有的随机数存在一个数组或集合中。但理解简单,操作简便。

方法二(直接发):占用内存更小,方法简洁

2.5 递归解法

逻辑分析:

  • 第一步:直接给采用随机数赋值–生成一个长度为m的随机数组arr

  • 第二步:对已经存有随机数的数组arr,进行去重,重新赋值

优劣:

该方法有许多重复判断,每次遇到重复的数后,需要将前面的数重新全部判断一遍是否重复。(不推荐,当然你也可以拿去优化一下)

代码如下:

package 随机不重复数组;

import java.util.Arrays;

public class Test2 {
    public static void main(String[] args) {
        // 测试--产生15个在0-30范围内的无重复的随机数
        int num = 15;
        int scope = 30;// 即取[0,19)中的整数
        // 方法三测试
        //创建随机数组:直接赋值随机数
        int[] numArray = new int[num];
        for (int i : numArray) {
            i = (int) (Math.random() * scope);
        }

        int[] test3Arr = isEqual(numArray, scope);
        System.out.println("方法三测试结果:" + Arrays.toString(test3Arr));
    }

    // 方法三:递归直接取值
    public static int[] isEqual(int[] numArray, int scope) {
        // 获得随机数
        int random = (int) (Math.random() * scope);

        // 给数组赋值---外层:给数组元素依次赋值
        for (int i = 1; i <= numArray.length - 1; i++) {
            // 内层:每次赋值后,与前面的数值进行比较,是否有重复

            // 若重复,就重新生成随机数赋值---若无重复,就给下一个数赋值
            for (int j = 0; j <= i - 1; j++) {
                // 判断是否有重复
                if (numArray[i] == numArray[j]) {
                    // 有重复就重新赋值
                    numArray[i] = random;
                    // 对新赋的值,进行判断
                    isEqual(numArray, scope);

                    break;
                }
            }
        }
        return numArray;
    }

}

运行结果

这里写图片描述

这里写图片描述

你可能感兴趣的:(TCB-算法,算法-名企面试)