生成不重複隨機數序列(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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章