Fisher-Yates shuffle和水库采样之间的差异

时间:2017-10-29 21:46:33

标签: algorithm math shuffle

我知道F-Y和水库采样都可以实现随机阵列。例如,我们在m * n的扫雷板中部署k炸弹。

我已经完成了示例代码:

public int[][] init2(int width, int length, int num){
    int[][] board = int[width][length];
    int[] bomb = new int[num];
    for(int i =0; i<num; i++){
        bomb[i] = i;
    }
    Random rand = new Random();
    for(int i = num; i<width*length; i++){
        int pos = rand.nextInt(i);
        if(pos < num){
            bomb[pos] = i;
        }
    }
    // TO DO
    // and then restore the pos to board        
}

// Fisher–Yates shuffle
public int[][] init3(int width, int length, int num){
    int[][] board = int[width][length];
    for(int i =0; i<num; i++){
        board[i%width][i/width] = 1;
    }
    Random rand = new Random();
    for(int i = num; i<width*length; i++){
        int pos = rand.nextInt(i+1);
        swap(board, i, pos);        
    }   
}

public void swap(int[][] board, int pos1, int pos2){
    int temp = board[pos1%width][pos1/width];
    board[pos1%width][pos1/width] = board[pos2%width][pos2/width];
    board[pos2%width][pos2/width] = temp;
}

我认为两者背后的数学是相同的,但我不知道为什么。 顺便说一句,如果我们在stackoverflow上输入代码,似乎我们不需要使用markdown。惊人!

1 个答案:

答案 0 :(得分:1)

两者之间的区别在于他们做了不同的事情:

+--------------+----------------+-----------------------------+------+-------+
| ALGORITHM    | INPUT(S)       | OUTPUT                      | TIME | SPACE |
+--------------+----------------+-----------------------------+------+-------+
| FISHER-YATES | n elements     | A list containing all n     | O(n) | O(n)  |
| SHUFFLE      |                | elements in a random order  |      |       |
+--------------+----------------+-----------------------------+------+-------+
| RESERVOIR    | n elements and | A set containing k of the n | O(n) | O(k)  |
| SAMPLING     | an integer k   | elements, selected randomly |      |       |
+--------------+----------------+-----------------------------+------+-------+

对于您的扫雷示例,您有 m × n 单元格,并且想要选择它们的 k ,这正是油藏采样所做的。因此,从概念上讲,这对我来说更合适。但是因为你打算使用 O m × n )空间 ,因为你的整个问题很可能不足以真正担心性能,我认为Fisher-Yates的方法也很好。 (它们在数学上都是合理的。)