生成不重复随机数序列(Java)

从1到n之间抽取出k个不重复的随机数,用Math.random()实现的话,可参照下面的代码。

int r = (int) (Math.random() * n), 生成下标,据此下标,去到numbers数组里拿到随机数。然后将numbers[r]的值设置成numbers[n-1]的值,下次抽取时,从numbers数组的前n-1个元素里抽取。以此类推,再下次,就是从umbers数组的前n-2个元素里抽取,直到抽完k个为止。

每次生成的下标是有可能重复的,但是由于numbers数组里该下标对应的值每抽中一次,就被踢出去了(替换成了n-1位置上的值),所以最终结果并不会重复。interesting…

公司年会抽奖,可以这种方法,将numbers数组初始化成在职的员工号序列即可:-)

package com.company;

import java.util.Arrays;
import java.util.Scanner;

public class LotteryDrawing {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("How many numbers do you need to draw?");
        int k = in.nextInt();
        System.out.println("What is the highest number you can draw?");
        int n = in.nextInt();
        int[] numbers = new int[n];
        for(int i = 0; i < n; i ++)
            numbers[i] = i + 1;

        int[] result = new int[k];
        for(int i = 0; i < result.length; i ++){
            //Math.random() generate double that between 0 and 1 (0 included, 1 not included)
            //int r represents the index that between 0 and n-1 (both included)
            int r = (int) (Math.random() * n);
            result[i] = numbers[r];
            numbers[r] = numbers[n-1];
            n --;
        }

        Arrays.sort(result);
        System.out.println("Lucky numbers: ");
        for(int i : result)
            System.out.println(i);
    }
}

程序输出:

How many numbers do you need to draw?
6
What is the highest number you can draw?
20
Lucky numbers: 
1
2
10
16
17
18

Java还有个Random类,用这个类也可以实现上述目标,基本思想是一样的。

package com.company;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
import java.util.List;

public class LotteryDrawing {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("How many numbers do you need to draw?");
        int k = in.nextInt();
        System.out.println("What is the highest number you can draw?");
        int n = in.nextInt();
        List<Integer> numbers = new ArrayList<>();
        for(int i = 0; i < n; i ++)
            numbers.add(i + 1);

        int[] result = new int[k];
        for(int i = 0; i < k; i ++){
            int r = generateRandomIndex(n - i);
            result[i] = numbers.get(r);
            numbers.remove(r);
        }

        Arrays.sort(result);
        System.out.println("Lucky numbers: ");
        for(int i : result)
            System.out.println(i);
    }
    private static int generateRandomIndex(int n){
        Random random = new Random();
        //return an int that between 0 and n, 0 included, n not included
        return random.nextInt(n);
    }
}

程序输出:

How many numbers do you need to draw?
6
What is the highest number you can draw?
20
Lucky numbers: 
6
7
8
11
12
13

在创建Random实例时,如果给定一个种子数字,那么这个实例生成出来的序列是一定的。比如,给定种子数字1,每一次运行时,它生成出来的序列都是5,8,7,3,4。

Random random = new Random(1);
     System.out.println(random.nextInt(10));
     System.out.println(random.nextInt(10));
     System.out.println(random.nextInt(10));
     System.out.println(random.nextInt(10));
     System.out.println(random.nextInt(10));

程序输出:

5
8
7
3
4

如果想要每次的序列不一样,那么新建实例时不要给种子数字,它会用系统时间作为种子数字(高并发的情况下,亦不能保证每次调用时系统时间都不一样…)

     Random random = new Random();
     System.out.println(random.nextInt(10));
     System.out.println(random.nextInt(10));
     System.out.println(random.nextInt(10));
     System.out.println(random.nextInt(10));
     System.out.println(random.nextInt(10));

第一次运行时程序输出:

7
9
4
0
3

第二次运行时程序输出

8
9
9
4
0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章