具有最少随机数的Java排列

时间:2009-11-14 15:39:56

标签: java math random permutation knuth

我想生成array a的排列,我不想使用java.util.Collections()等实用功能。
排列应该随机化并且每个排列都应该可能发生 - 但是不需要均匀分布的概率。

以下代码实现了这一点 - 但性能不佳:

// array holding 1,...,n
// initialized somewhere else
int[] a = new int[N];

for (int i = 0; i < a.length ; i++) {
     int r = (int) (Math.random() * (i+1));     
     swap(r,i,a);
  }

private static void swap(int j, int k, int[] array){
      int temp = array[k];
      array[k] = array[j];
      array[j] = temp;
}

问题
是否有可能减少用于生成排列的随机数总数?

3 个答案:

答案 0 :(得分:4)

如果有人对Knuth shuffle进行了改进,我会感到惊讶。这是O(n)。

  

需要O(n)随机数,这对我来说还不够。

This citation声称有一个O(n log n)算法。

我们都希望看到O(log n)或O(1)。

O(log n)算法通常依赖于“分而治之”的二分法,这会让人想到切割甲板并将每一半分开。

但我不禁想到,如果可以使用更快的算法,Knuth就会找到它。

答案 1 :(得分:2)

长度为n的序列有n!排列。如果每个都需要进行排列,那么每个排列都必须有一系列随机数。

要随机置换长度为n的数组,您可以生成1..n范围内的单个随机数!均匀随意。这标识了单个排列,然后您可以应用它。

您可以改进您的问题,询问需要多少随机位。通过相同的论证,那将是log(n!)。为了让您了解该函数的渐近行为,请考虑:

设n&gt; 3:

n = log(2 ^ n)&lt; log(n!)&lt; log(n ^ n)= n * log(n)

因此n个随机位不够(对于n> 3)。实际上,可以证明log(n!)不在O(n)中。

答案 2 :(得分:1)

我能想到的唯一可能的优化是使随机数生成器更快。一个简单的解决方案是首先生成随机整数:

import java.util.Random;
Random rand = new Random();

for (int i = 0; i < a.length ; i++) {
    swap(rand.nextInt(i+1), i, a);
}

...

或者,您可以发明一种更快或更少的随机数生成方式(均匀分布或不分配,适合您的需要)。但是,你无法克服O(n)限制。

相关问题