Java中统一生成随机置换

Java中统一生成随机置换,java,permutation,discrete-mathematics,Java,Permutation,Discrete Mathematics,任何人都知道Java中生成整数列表随机排列的快速/最快方法。例如,如果我想要一个长度为5的随机排列,答案将是15423,其中每个5可能性同样可能 我对如何解决这个问题的想法是运行一种方法,该方法在所需长度的数组中生成随机实数,然后对它们进行排序,返回索引,即0.712 0.314 0.42 0.69 0.1将返回5 2 3 4 1的排列。我认为这是有可能在O(n^2)中运行的,目前我的代码大约在O(n^3)中运行,这是目前我程序运行时间的很大一部分。从理论上讲,这似乎还可以,但我不确定在实践中是

任何人都知道Java中生成整数列表随机排列的快速/最快方法。例如,如果我想要一个长度为5的随机排列,答案将是
15423
,其中每个
5可能性同样可能


我对如何解决这个问题的想法是运行一种方法,该方法在所需长度的数组中生成随机实数,然后对它们进行排序,返回索引,即
0.712 0.314 0.42 0.69 0.1
将返回
5 2 3 4 1
的排列。我认为这是有可能在
O(n^2)
中运行的,目前我的代码大约在
O(n^3)
中运行,这是目前我程序运行时间的很大一部分。从理论上讲,这似乎还可以,但我不确定在实践中是否可行。

您尝试过以下方法吗

Collections.shuffle(list)

这将遍历每个元素,将该元素与随机剩余的元素交换。这有一个O(n)时间复杂度。

有一个O(n)方法很容易实现。

如果目的只是生成一个随机排列,我真的不理解排序的必要性。据我所知,下面的代码以线性时间运行

public static int[] getRandomPermutation (int length){

    // initialize array and fill it with {0,1,2...}
    int[] array = new int[length];
    for(int i = 0; i < array.length; i++)
        array[i] = i;

    for(int i = 0; i < length; i++){

        // randomly chosen position in array whose element
        // will be swapped with the element in position i
        // note that when i = 0, any position can chosen (0 thru length-1)
        // when i = 1, only positions 1 through length -1
                    // NOTE: r is an instance of java.util.Random
        int ran = i + r.nextInt (length-i);

        // perform swap
        int temp = array[i];
        array[i] = array[ran];
        array[ran] = temp;
    }                       
    return array;
}
publicstaticint[]getRandomPermutation(int-length){
//初始化数组并用{0,1,2…}填充它
int[]数组=新的int[length];
for(int i=0;i
下面是一些测试它的代码:

public static void testGetRandomPermutation () {

    int length =4;  // length of arrays to construct

    // This code tests the DISTRIBUTIONAL PROPERTIES
    ArrayList<Integer> counts = new ArrayList <Integer> ();  // filled with Integer
    ArrayList<int[]> arrays = new ArrayList <int[]> ();  // filled with int[]

    int T = 1000000; // number of trials
    for (int t = 0; t < T; t++) {           
        int[] perm = getRandomPermutation(length);
        // System.out.println (getString (perm));
        boolean matchFound = false;
        for(int j = 0; j < arrays.size(); j++) {
            if(equals(perm,arrays.get(j))) {
                //System.out.println ("match found!");
                matchFound = true;
                // increment value of count in corresponding position of count list
                counts.set(j, Integer.valueOf(counts.get(j).intValue()+1));
                break;
    }                       
        }
        if (!matchFound) {
            arrays.add(perm);
            counts.add(Integer.valueOf(1));
        }   
    }

    for(int i = 0; i < arrays.size(); i++){
        System.out.println (getString (arrays.get (i)));
        System.out.println ("frequency: " + counts.get (i).intValue ());
    }

    // Now let's test the speed
    T = 500000;  // trials per array length n       
    // n will the the length of the arrays
    double[] times = new double[97];
    for(int n = 3; n < 100; n++){
        long beginTime = System.currentTimeMillis();
        for(int t = 0; t < T; t++){
            int[] perm = getRandomPermutation(n);
        }
        long endTime = System.currentTimeMillis();
        times[n-3] = (double)(endTime-beginTime);
        System.out.println("time to make "+T+" random permutations of length "+n+" : "+ (endTime-beginTime));
    }
    // Plotter.plot(new double[][]{times});     
}
公共静态void testGetRandomPermutation(){
int length=4;//要构造的数组的长度
//此代码测试分布属性
ArrayList counts=new ArrayList();//用整数填充
ArrayList数组=新的ArrayList();//用int[]填充
int T=1000000;//试验次数
对于(int t=0;t
只需在
0
n!-1
并使用

.

每个结果的可能性相同吗?我不确定它是否有内在的偏见?如果它的行为符合我和你的建议,为什么你会怀疑这一点?你的疑问是什么?From“使用默认的随机性源随机排列指定的列表。所有排列的可能性大致相等。hedge”大约“在前面的描述中使用,因为默认随机性源只是独立选择位的近似无偏源。如果它是随机选择位的完美来源,那么算法将选择具有完美一致性的排列。“如果您使用
Random
,您自己的实现在最佳情况下与
集合一样好。shuffle(列表)
我不确定,因为我对它不太熟悉。无论如何,谢谢你的提示。你关于该方法时间复杂度的陈述是不准确的。它是线性时间。实际上,Collections.shuffle方法正好实现了这个算法。(我发现,阅读了文档…)还有Knuth的洗牌算法:@Loadmaster,你的维基百科链接从答案重定向到链接。:P