从N个数中等概率打印M个数

题目:给定一个长度为n且"没有重复元素"的数组array和一个整数m,实现函数等概论随机打印array中的m个数。


要求:

1.相同的数不要重复打印

2.时间复杂度为O(M),额外空间复杂度为O(1)

3.可以改变array数组


解题思路:

解法的关键点是利用要求3改变数组array。打印过程如下:

1.在[0, N - 1]中随机得到一个位置a,然后打印array[a]

2.把array[a]和array[n - 1]交换

3.在[0, n - 2]中随机得到一个位置b,然后打印array[b],因为打印过的arraya[a]已经被换到了

n-1位置,所以这次打印不可能再次出现。

4.把array[b]和array[n - 2]交换

5.在[0.n-3]中随机得到一个数c,然后打印array[c],因为打印过的array[a]和array[b]已经被换到了

n-1位置和n-2位置,所以这次打印都不可能再出现。

6.以此类推,直到打印m个数


总之,就是把随机选出来的数打印出来,然后将打印的数交换到范围中的最后位置,再把范围缩小,使得被打印的数下次

不可能再被选中,直到打印结束。很多有关等概论随机的面试题都是使用这种和最后一个位置交换的解法。


public class RandomM {

    public void printRandM(int[] array, int m){

        if(array == null || array.length == 0 || m < 0){
            return;
        }

        m = Math.max(array.length, m);
        int count = 0;
        int i = 0;
        while(count < m){
            i = (int)(Math.random() * (array.length - count));
            System.out.println(array[i]);
            swap(array,array.length - count++ - 1, i);
        }
    }

    public void swap(int[] array, int index1, int index2){
        int temp = array[index1];
        array[index1] = array[index2];
        array[index2] = temp;
    }
}


猜你喜欢

转载自blog.csdn.net/hoji_James/article/details/80600599