[英]Picking different random elements from int array each time in iteration?
我有一個int向量,例如int[] A = {6, 1, 5, 3, 4, 2}
,我需要在三個步驟中隨機選擇兩個不同的元素,並且每個步驟都應該從其他步驟中挑選出不同的元素。
例如:
我嘗試這樣做,但失敗了很多次。 我將非常感謝您的幫助。 這是我的最后一個代碼。
public class T8 {
public static void main(String[] args) {
int n=5, d=2, r, i, j;
int[] B = new int [d];
Random rand=new Random();
System.out.println("d = "+d);
Integer[] A = {10,12,3,4,5};
List<Integer> list = new ArrayList<Integer>(Arrays.asList(A));
for(j=0; j<d; j++){
r = rand.nextInt(n);
B[j] = A[r];
System.out.print(B[j]+" ");
list.remove(r);
A = list.toArray(new Integer[0]);
n=n-1;
}
System.out.println("");
for(j=0; j<n; j++){
System.out.print(A[j]+" ");
}
}
}
不是最佳方法 :可以使用random.nextInt,並且每次生成隨機數時,請檢查其是否唯一,如果不生成新的隨機索引。 例如
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class RandomPicker {
public static void main(String[] args) {
int[] arr = {6, 1, 5, 3, 4, 2};
Random random = new Random();
Set<Integer> randoms = new HashSet<>();
while (arr.length != randoms.size()) {
int i = nextRandomIndex(arr, random, randoms);
int j = nextRandomIndex(arr, random, randoms);
System.out.printf("%d,%d\n", arr[i], arr[j]);
}
}
private static int nextRandomIndex(int[] arr, Random random, Set<Integer> randoms) {
int i = random.nextInt(arr.length);
while (randoms.contains(i)) {
i= random.nextInt(arr.length);
}
randoms.add(i);
return i;
}
}
可能的輸出
4,1
6,3
5,2
更好的方法是先對數組進行隨機排序,然后對其進行迭代(如果您不想修改數組,則將原始數組的副本傳遞給shuffle方法)。 例如
import java.util.Arrays;
import java.util.Random;
public class RandomPicker {
public static void main(String[] args) {
int[] arr = {6, 1, 5, 3, 4, 2};
int[] copy = Arrays.copyOf(arr, arr.length);
shuffle(copy);
int index = 0;
for (int i = 0; i < arr.length / 2; i++) {
System.out.printf("%d, %d\n",copy[index], copy[++index]);
}
}
private static void shuffle(int[] arr)
{
int index;
int temp;
Random rand = new Random();
int i = arr.length - 1;
while ( i > 0)
{
index = rand.nextInt(i + 1);
temp = arr[index];
arr[index] = arr[i];
arr[i] = temp;
i--;
}
}
}
您可以通過多種方式執行此操作:
將數組元素復制到List
,然后從列表中隨機刪除元素。
使用(弱)偽隨機數生成器以可預測的方式循環遍歷所有索引。
為您之前返回的所有元素創建一個HashSet
。
使用shuffle
方法就地重組輸入數組,然后一次從索引0
開始一次返回一個元素,直到達到length - 1
為止。
如果您無法更改輸入數組,則創建一個數組,將值0
填充為length - 1
,將其洗牌,然后使用其值作為第一個數組的索引逐步遍歷該數組。
@ sol4me的解決方案(由上面的3.和5.混合而成)具有有趣的屬性。 計算行為是概率性的:
當您到達序列的末尾時,“警報”增長之前查找和返回未使用的索引所花費的時間。
理論上最壞的情況是nextRandomIndex
永不終止。 (只有在您的隨機數生成器有偏見的情況下,這種情況才會發生。)
對於“完美”的隨機數生成器, nextRandomIndex
執行的迭代次數是有限的,但是我們不能對其設置上限。
對於偽隨機數生成器,生成器的循環長度是迭代次數的上限。
您嘗試的解決方案接近我建議的第一個解決方案。 但是一個問題是
List<Integer> list = new ArrayList<Integer>(Arrays.asList(A));
在無法更改其長度的數組上創建“視圖”。 如果創建一個ArrayList
,然后將數組元素復制到列表中,則不會獲得在remove
中看到的異常。
另一個問題是:
A = list.toArray(new Integer[0]);
效率很低。 不必將列表轉換回數組。 請保留下一次清單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.