问题描述
因此,我在程序中使用了一个偏好矩阵(2d数组),其中每个人将其他成员的排名从最有利到最不利。个人在数组中排名最后。
例如:
{[1,2,3,4,5,0],[2,1],[3,1,2],[4,3],[5,4],[0,5]}
我该如何随机生成上面的矩阵,其中最后一个元素代表用户的数字0-n,其余n-1个元素是随机序列中的任意数字?
解决方法
您可以使用Collections.shuffle(list)
来随机排列任何列表,但是奇怪的是,Java API没有Arrays.shuffle(arr)
,并且将int[]
变成了一个集合,因此您可以将其提供给{ {1}}效率很低。
对于您拥有的最大集,这真的没有关系;只有在我们谈论100,000个或更多数字时,这才成为问题。
因此,一种简单易读的方法是列出除该人自己的索引之外的所有元素的列表,将其洗牌,最后将用户的索引折腾,然后瞧瞧:
Collections.shuffle
如果您确实确实需要一种运行效率尽可能高的算法,则必须制作一个public int[][] makeRandom(int n) {
int[][] out = new int[n][];
for (int i = 0; i < n; i++) { // for each person
// make a list of their preferences
List<Integer> list = new ArrayList<Integer>();
for (int j = 0; j < n; j++) {
// add everybody except yourself
if (j != i) list.add(j);
}
Collections.shuffle(list); // randomize
list.add(i); // add yourself
// turn into an int array
int[] arr = list.stream().mapToInt(Integer::intValue).toArray();
// set the int array,representing person i's prefs.
out[i] = arr;
}
return out;
}
的新实例,并使用其java.util.Random
方法,以便可以应用{ {3}}可以自己在现有的int数组列表上进行随机播放算法,甚至可以方便地在随机播放期间跳过数组中的最后一个数字。那将是更多的代码,需要更多的复杂注释。无论如何,请放心,但我将其留给读者练习。
我如何随机生成一个与上述矩阵相同的矩阵,其中最后一个元素表示用户的数字0-n,其余n-1个元素是随机序列中的任意数字? 这是另一种方法。
int n = 6;
这定义了一个简单的lambda来
- 有效地将用户号码移动到数组的末尾
- 随机排列数组,不包括最后一个元素(用户的编号)。
BiFunction<int[],Integer,int[]> shuffle = (ar,ii)->{
int len = ar.length-1;
ar[len] = ar[ii];
ar[ii] = len--;
while (len >= 0) {
int i = (int)(Math.random()*len);
int t = ar[i];
ar[i] = ar[len];
ar[len--]=t;
}
return ar;
};
现在构建一个从0 to n
开始的数组。
int[] arr = IntStream.range(0,n).toArray();
shuffle
到阵列和move
用户到阵列的时间
结束并创建最终的数组数组。
int[][] darr = IntStream.range(0,n)
.mapToObj(i -> shuffle.apply(arr.clone(),i))
.toArray(int[][]::new);
现在打印它们
for (int[] a : darr) {
System.out.println(Arrays.toString(a));
}
对于n = 6
,打印
[2,4,3,1,5,0]
[2,1]
[4,2]
[4,2,3]
[5,4]
[3,5]
,
编辑: 首先生成矩阵,其中每行数字变为0,2 ... n-1 之后,在每个矩阵的行上调用shuffle方法。
以下是简短的代码段:
public int[][] generateRandomMatrix(int rows,int cols){
int[][] matrix = new int[rows][cols];
for(int i=0;i<rows;i++) {
for(int j=0;j<cols;j++) {
matrix[i][j]=j;
}
shuffle(matrix[i]);
}
return matrix;
}
public void shuffle(int[] arrray){
Random r = ThreadLocalRandom.current();
int n = arrray.length;
for (int i=0;i<n;i++){
int index = r.nextInt(i + 1);
int a = arrray[index];
arrray[index] = arrray[i];
arrray[i] = a;
}
}