1. 程式人生 > >生成不重複隨機數序列(Java)

生成不重複隨機數序列(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