生成随机矩阵的最佳方法在Java中是:

huangapple go评论73阅读模式
英文:

The best way to generate a randomised matrix in Java

问题

Sure, here's the translation of the provided content:

所以我在我的程序中使用了一个偏好矩阵(2D数组),其中每个人将其他成员从最喜欢到最不喜欢进行排名。个人将自己排在数组的最后。

例如:

{[1, 2, 3, 4, 5, 0],
 [2, 3, 4, 5, 0, 1],
 [3, 4, 5, 0, 1, 2],
 [4, 5, 0, 1, 2, 3],
 [5, 0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4, 5]}

我如何随机生成一个类似上面的矩阵,其中最后一个元素代表用户的数字0-n,其余的n-1个元素是随机顺序中的任意数字?

英文:

So I'm using a preference matrix (2d array) within my program, in which each person ranks the other members from most favorable to least favorable. The individual ranks themselves last in the array.

For example:

{[1, 2, 3, 4, 5, 0],
 [2, 3, 4, 5, 0, 1],
 [3, 4, 5, 0, 1, 2],
 [4, 5, 0, 1, 2, 3],
 [5, 0, 1, 2, 3, 4],
 [0, 1, 2, 3, 4, 5]}

How can I randomly generate a matrix like the one above, where the last element represents the user's number 0-n and the remaining n-1 elements are arbitrary numbers in a random sequence?

答案1

得分: 0

你可以使用 Collections.shuffle(list) 来随机排列任何列表,但奇怪的是,Java API 没有 Arrays.shuffle(arr),将 int[] 转换成集合以便传递给 Collections.shuffle 是相当低效的。

对于像你所拥有的这么大的集合,这实际上并不重要;只有当我们谈论 100,000 个数字或更多时,这才会成为一个问题。

因此,简单且可读的方式是创建一个除了个人自己索引之外的所有元素的列表,对该列表进行洗牌,然后将用户的索引放在最后,就可以了:

public int[][] makeRandom(int n) {
  int[][] out = new int[n][];

  for (int i = 0; i < n; i++) { // 对于每个人
    // 创建他们偏好的列表
    List<Integer> list = new ArrayList<Integer>();
    for (int j = 0; j < n; j++) {
      // 添加除了自己以外的每个人
      if (j != i) list.add(j);
    }
    Collections.shuffle(list); // 随机化
    list.add(i); // 添加自己
    // 转换成 int 数组
    int[] arr = list.stream().mapToInt(Integer::intValue).toArray();
    // 设置表示个人 i 偏好的 int 数组
    out[i] = arr;
  }

  return out;
}

如果你真的需要一个尽可能高效的算法,你将需要创建一个新的 java.util.Random 实例,并使用其 .nextInt() 方法,以便你可以自己在现有的 int 数组列表上应用 Fisher-yates 洗牌算法,方便地在洗牌过程中跳过数组中的最后一个数字。那将需要更多的代码,并需要更复杂的注释。当然,随意尝试,但我将把这留给读者作为练习。

英文:

You can use Collections.shuffle(list) to shuffle any list, but bizarrely, the java API does not have an Arrays.shuffle(arr), and turning an int[] into a collection so you can feed it to Collections.shuffle is rather inefficient.

For sets as large as you have, that really doesn't matter; that only becomes an issue once we're talking about 100,000 numbers or more.

So, the easy, readable way, is to make a list of all elements except the person's own index, shuffle that, toss the user's index at the very end, and voila:

public int[][] makeRandom(int n) {
  int[][] out = new int[n][];

  for (int i = 0; i &lt; n; i++) { // for each person
    // make a list of their preferences
    List&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;();
    for (int j = 0; j &lt; 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&#39;s prefs.
    out[i] = arr;
  }

  return out;
}

If you really do need an algorithm that runs as efficient as can be, you'd have to make a new instance of java.util.Random, and use its .nextInt() method so that you can apply the Fisher-yates shuffle algorithm yourself, in-place, on an existing int array list, even conveniently skipping the very last number in the array during your shuffle. That'd be a lot more code that requires a lot more convoluted comments. By all means, feel free, but I'll leave that as an exercise to the reader.

答案2

得分: 0

以下是翻译好的部分:

如何随机生成一个类似上面的矩阵,其中最后一个元素表示用户的数字 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 到 n 的单一数组。

int[] arr = IntStream.range(0, n).toArray();

现在是时候对数组进行 shuffle 并将用户移动到末尾,并创建最终的数组。

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, 4, 5, 0, 3, 1]
[4, 5, 3, 0, 1, 2]
[4, 0, 5, 1, 2, 3]
[5, 3, 0, 2, 1, 4]
[3, 0, 4, 2, 1, 5]

请注意,代码部分不会被翻译。

英文:

> How can I randomly generate a matrix like the one above, where the last element represents the user's number 0-n and the remaining n-1 elements are arbitrary numbers in a random sequence?
Here is another way to do it.

int n = 6;

This defines a simple lambda to

  • effectively move the user's number to the end of the array
  • shuffle the array, excluding the last element (user's no).
BiFunction&lt;int[],Integer,int[]&gt; shuffle = (ar,ii)-&gt;{
	int len = ar.length-1;
	ar[len] = ar[ii];
	ar[ii] = len--;
	while (len &gt;= 0) {
		int i = (int)(Math.random()*len);
		int t = ar[i];
		ar[i] = ar[len];
		ar[len--]=t;
	}
	return ar;
};
	

Now build a single array that goes from 0 to n.

int[] arr = IntStream.range(0, n).toArray();

Time to shuffle the array and move the user to the
end and create the final array of arrays.

int[][] darr = IntStream.range(0, n)
		.mapToObj(i -&gt; shuffle.apply(arr.clone(), i))
		.toArray(int[][]::new);

Now print them

for (int[] a : darr) {
	System.out.println(Arrays.toString(a));
}

For n = 6, prints

[2, 4, 3, 1, 5, 0]
[2, 4, 5, 0, 3, 1]
[4, 5, 3, 0, 1, 2]
[4, 0, 5, 1, 2, 3]
[5, 3, 0, 2, 1, 4]
[3, 0, 4, 2, 1, 5]



</details>



# 答案3
**得分**: -1

编辑:
首先生成矩阵,其中每行的数字为 0、1、2...n-1。
之后在每个矩阵的行上调用 shuffle 方法。

以下是简短的代码片段:
```java
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[] array){
    Random r = ThreadLocalRandom.current();
    int n = array.length;
    for (int i=0; i<n; i++){
        int index = r.nextInt(i + 1);
        int a = array[index];
        array[index] = array[i];
        array[i] = a;
    }
}
英文:

Edit:
First generate matrix in which number in each row goes 0,1,2...n-1
After that call shuffle method on each matrix's row.

Here is short code snippet:

public int[][] generateRandomMatrix(int rows,int cols){
		int[][] matrix = new int[rows][cols];
		for(int i=0;i&lt;rows;i++) {
			for(int j=0;j&lt;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&lt;n;i++){
	      int index = r.nextInt(i + 1);
	      int a = arrray[index];
	      arrray[index] = arrray[i];
	      arrray[i] = a;
	    }
	  }

huangapple
  • 本文由 发表于 2020年8月12日 05:10:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/63366415.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定