2014-12-07 58 views
0

我有一個int向量,如int[] A = {6, 1, 5, 3, 4, 2},我需要在三個步驟中隨機選取兩個不同的元素,並且每個步驟應該從其他步驟中挑選不同的元素。每次在迭代中從int數組中挑選不同的隨機元素?

例如:

  1. 選擇2,5
  2. 選擇6,3
  3. 選擇4,1

我嘗試這樣做,但我失敗了很多次。我會很感激任何幫助。 這是我最後的代碼。

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]+" "); 
     } 
    } 
} 
+2

你試過了什麼代碼? – markspace 2014-12-07 00:24:27

+0

一種可能的方法是:將選中的每個元素捕獲到該選項的變量中,然後將其在原始數組中的索引設置爲無效值,然後知道您已經選擇了什麼。然後把所有的元素都放回去。 – abiessu 2014-12-07 00:31:05

+0

非常感謝,我已經通過加入我自己的代碼編輯了帖子。 – John 2014-12-07 00:34:10

回答

0

不是最佳的辦法:您可以使用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 

更好的辦法是重新洗牌數組,然後遍歷它(如果你不想修改數組,然後通過原始數組洗牌方法的副本)。例如。

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--; 
     } 
    } 
} 
+0

非常感謝,我現在就試試。 – John 2014-12-07 00:35:04

+0

非常感謝你的工作,再次感謝。 – John 2014-12-08 14:25:26

0

許多方式,你可以這樣做:

  1. 複製數組元素成List然後隨機從列表中刪除元素。

  2. 使用一個(弱)僞隨機數發生器,以可預測的方式遍歷所有索引。

  3. 創建之前返回的所有元素的HashSet

  4. 使用shuffle方法洗牌就地輸入數組,然後只返回在時間中的元素一個,直到你達到length - 1從指數0開始。

  5. 如果不能改變輸入陣列,則創建填充值0length - 1陣列,混洗陣列,然後通過使用其值作爲索引到所述第一陣列,其陣列步驟。

@ sol4me的解決方案(它是上述3.和5.的混合)具有一個有趣的屬性。計算行爲是概率:

  • 當你到達的順序,找到並返回尚未使用的索引之前的增長「令人擔憂」所花費的時間結束。

  • 理論上的最壞情況行爲是nextRandomIndex永不終止。 (只有當你的隨機數發生器有偏差時,纔會發生這種情況。)

  • 對於「完美」的隨機數發生器,由nextRandomIndex執行的迭代次數是有限的,但我們不能在它上面放置一個上限。

  • 對於僞隨機數發生器,發生器的週期長度是迭代次數的上限。


你嘗試的解決方案是接近第一個我建議。但有一個問題是,

List<Integer> list = new ArrayList<Integer>(Arrays.asList(A)); 

是創建一個「視圖」到陣列,其長度不能改變。如果您創建一個ArrayList,然後數組元素複製到列表中,則不會在remove中看到例外情況。

另一個問題是這樣的:

A = list.toArray(new Integer[0]); 

是非常低效。不需要將列表轉換回數組。只需保留下次列表。

+0

非常感謝,您的意見非常有用,非常感謝。 – John 2014-12-08 14:26:12

相關問題