2013-04-14 207 views
22

我想在Java中創建一組沒有重複的隨機數。Java生成非重複的隨機數

比如我有一個數組從0萬個的隨機整數存儲9999

這是我到目前爲止有:

import java.util.Random; 
public class Sort{ 

    public static void main(String[] args){ 

     int[] nums = new int[10000]; 

     Random randomGenerator = new Random(); 

     for (int i = 0; i < nums.length; ++i){ 
      nums[i] = randomGenerator.nextInt(10000); 
     } 
    } 
} 

但上面的代碼創建副本。我怎樣才能確保隨機數字不會重複?

+1

可能重複的[生成uniq ue隨機數在Java](http://stackoverflow.com/questions/9423523/generate-unique-random-numbers-in-java) –

+2

但如果你刪除重複的數字,那麼他們不是隨機 –

+1

你想要*以隨機順序排列數組中的所有* 10.000數字,還是您想要10.000個隨機數字?因爲你不能在0 - 9.999的範圍內有10.000個隨機數(然後他們不是隨機的) – GameDroids

回答

32
Integer[] arr = {...}; 
Collections.shuffle(Arrays.asList(arr)); 

例如:

public static void main(String[] args) { 
    Integer[] arr = new Integer[1000]; 
    for (int i = 0; i < arr.length; i++) { 
     arr[i] = i; 
    } 
    Collections.shuffle(Arrays.asList(arr)); 
    System.out.println(Arrays.toString(arr)); 

} 
+1

Shuffle很棒,但首先應該創建包含數字的數組從0到9999,然後洗牌。另外,洗牌的時間複雜度是多少? – Martinsos

+1

@Martinsos我創建了數組並對其進行了整理。我不確定,但我認爲洗牌的時間複雜度應該是O(n)。因爲如果只是在數組內隨機交換。 –

2

Achintya桑傑·賈在這裏有正確的想法。不要考慮如何刪除重複項,而是首先刪除創建重複項的功能。

如果您想要使用一系列整數並想要隨機化它們的順序(手動,這很簡單),請按照下列步驟操作。

  1. 創建大小爲n的數組。
  2. 循環並將索引i處的每個值初始化爲值i(或如果您希望將數字1至n而非0至n-1,則i + 1)。
  3. 最後,循環遍歷數組,再次交換每個值的隨機索引值。

你的代碼可以被修改,看起來像這樣:

import java.util.Random; 

public class Sort 
{ 
    // use a constant rather than having the "magic number" 10000 scattered about 
    public static final int N = 10000; 

    public static void main(String[] args) 
    { 
     //array to store N random integers (0 - N-1) 
     int[] nums = new int[N]; 

     // initialize each value at index i to the value i 
     for (int i = 0; i < nums.length; ++i) 
     { 
      nums[i] = i; 
     } 

     Random randomGenerator = new Random(); 
     int randomIndex; // the randomly selected index each time through the loop 
     int randomValue; // the value at nums[randomIndex] each time through the loop 

     // randomize order of values 
     for(int i = 0; i < nums.length; ++i) 
     { 
      // select a random index 
      randomIndex = randomGenerator.nextInt(nums.length); 

      // swap values 
      randomValue = nums[randomIndex]; 
      nums[randomIndex] = nums[i]; 
      nums[i] = randomValue; 
     } 
    } 
} 

如果我是你,我可能會打破這些塊到單獨的,較小的方法,而不是一個大的主要方法。

希望這會有所幫助。

0
public class Randoms { 

static int z, a = 1111, b = 9999, r; 

public static void main(String ... args[]) 
{ 
     rand(); 
} 

    public static void rand() { 

    Random ran = new Random(); 
    for (int i = 1; i == 1; i++) { 
     z = ran.nextInt(b - a + 1) + a; 
     System.out.println(z); 
     randcheck(); 
    } 
} 

private static void randcheck() { 

    for (int i = 3; i >= 0; i--) { 
     if (z != 0) { 
      r = z % 10; 
      arr[i] = r; 
      z = z/10; 
     } 
    } 
    for (int i = 0; i <= 3; i++) { 
     for (int j = i + 1; j <= 3; j++) { 
      if (arr[i] == arr[j]) { 
       rand(); 
      } 
     } 

    } 
} 
} 
6

一個簡單的算法,爲您提供沒有重複的隨機數字可以在Programming Pearls第p頁找到。 127.

注意力:結果數組按順序包含數字!如果您希望以隨機順序排列它們,則必須使用Fisher–Yates shuffle或通過使用列表並撥打電話Collections.shuffle()來隨機排列陣列。

該算法的好處是,您不需要創建一個包含所有可能數字的數組,並且運行時複雜度仍然是線性的O(n)

public static int[] sampleRandomNumbersWithoutRepetition(int start, int end, int count) { 
    Random rng = new Random(); 

    int[] result = new int[count]; 
    int cur = 0; 
    int remaining = end - start; 
    for (int i = start; i < end && count > 0; i++) { 
     double probability = rng.nextDouble(); 
     if (probability < ((double) count)/(double) remaining) { 
      count--; 
      result[cur++] = i; 
     } 
     remaining--; 
    } 
    return result; 
} 
+1

注意:(re:你的「注意」部分)'Collections.shuffle'正在做一個Fisher-Yates shuffle,所以它不是一個「或 - 或」的情況。 –

+0

你是對的,'Collections.shuffle'做了Fisher-Yates洗牌,但是你需要一個List來使用它。 'Arrays.asList'需要數組的類型爲'Integer'而不是'int'來正確地進行轉換,那麼你不必分配額外的內存。 編寫Fisher-Yates隨機播放避免了轉換,並且不需要額外的內存。 – the

1

這個怎麼樣?

LinkedHashSet<Integer> test = new LinkedHashSet<Integer>(); 
Random random = new Random(); 
do{ 
    test.add(random.nextInt(1000) + 1); 
}while(test.size() != 1000); 

用戶可以使用for循環遍歷Set

2

如果你需要生成間隔號碼,也可以只是這樣:

Integer[] arr = new Integer[((int) (Math.random() * (16 - 30) + 30))]; 
for (int i = 0; i < arr.length; i++) { 
arr[i] = i; 
} 
Collections.shuffle(Arrays.asList(arr)); 
System.out.println(Arrays.toString(arr));` 

結果:

[1, 10, 2, 4, 9, 8, 7, 13, 18, 17, 5, 21, 12, 16, 23, 20, 6, 0, 22, 14, 24, 15, 3, 11, 19]

注:

如果您需要的是零不留下你可以把一個「如果」