2014-07-01 196 views
3

如何在1到9之間生成9個隨機數,而不是重複,一個接一個。它是這樣的: 假設生成的第一個隨機數是4,那麼下一個隨機數必須在[1,9] - {4}中。 我的第一種方法是將每個隨機生成的數字添加到一個集合中,以避免重複。但是在更糟糕的情況下,就像我們已經生成了6並且我們必須生成3個數字一樣,這個過程有點慢。當範圍從[1,9]改變爲[1,1000]時,這種方法聽起來不正確。 任何人都可以提出一種替代方法。生成唯一的隨機數

+1

您可以將剛選擇的數字與最後一個數字交換,並假裝在下一步中您將從短一個元素的數組中選擇。 –

+0

產生一個數字,並保持其頻率計數..如果頻率> 0產生另一個隨機數字和加法或減法或做一些數學運算來獲得另一個數字。雖然這也將非常忙碌作業 – rock321987

+1

您需要生成一個排列並從排列中進行選擇。如果你可以保存所有內存 – odedsh

回答

2

以下是兩種可能的方法: -

方法1: -

  1. 在與大小爲n的數組所有數字。
  2. 選擇一些隨機I =蘭特(0,大小)
  3. 打印ARR [I]
  4. 交換ARR索引[i]和ARR [大小-1]
  5. 大小= -1
  6. 重複1到5直到列表被耗盡。

時間複雜度:O(N)

空間複雜:O(N)

方法2: -

  1. 選擇池大小K.
  2. 生成K個隨機整數。
  3. 將它們顯示爲前k個結果。
  4. 將它們添加到哈希集。
  5. 爲池中所有以前的整數添加所有ak + 1。
  6. 如果它不在哈希集中,則添加1。
  7. 從池中隨機選取一個整數r並顯示它。
  8. 將r + 1添加到池中,如果它不在哈希集中
  9. 做7到8直到池被耗盡。

時間複雜度:O(N)

空間的複雜性:O(K)

臨&缺點: -

方法1:使用此方法對於小整數範圍,因爲它需要更大的空間,但它非常快速和隨機。

方法2:對於更大的範圍使用此方法,因爲它需要您選擇的內存O(K)。 k越高,生成的數字的隨機性越高。因此,您可以在保持良好速度的情況下在空間和隨機性之間取得良好的折衷。

5

從排序數組開始(通過for-loop方便創建trivialy);然後將每個數組元素與另一個(隨機選擇的)元素交換。 爲了避免評論中討論的偏見,其他元素的索引必須等於或高於第一個元素的索引。 如果索引相等,則該元素不交換。 (這個答案的原始版本包含一個關於被交換回元素的可能性句話,但是這是現在已經過時了,因爲這不能用高亮修改再發生)

+3

事實上,這個看似正確的算法[實際上是隨機洗牌](http:// blog。 codinghorror.com/the-danger-of-naivete/)。 –

+3

爲了得到一個無偏見的隨機播放,你需要確保你只用一個隨機選擇的* *後面的*元素或者它自己(即不交換)來交換每個元素。 –

+0

@j_random_hacker:哇,謝謝你的信息! –

0

創建這樣一個ArrayList:

指數0->指數1->索引2 ...

[1] - > [2] - > [3] ....

生成隨機索引值介乎0和列表.size()並獲取列表中的位置:

yourNumberResult = get(randomIndexValue)。

然後刪除列表中的位置:

list.remove(randomIndexValue)

然後在反覆重複這一點,直到則爲list.size()== 0

+1

請注意,從ArrayList移除項目效率不高,因爲所有移除後的項目必須向下移動以填補空白。在大型陣列上重複執行此操作會導致大量內存流量,這可能是瓶頸。 – Wyzard

+0

我想交換,而不是刪除會更快,但是,謝謝你的算法 – gonephishing

+0

我不知道,因爲交換算法是非常複雜的。我認爲對於<10000的列表,你沒有性能差異,但如果它很重要,請嘗試兩種方法並計算時間。 –

4

如果你不感興趣實現你自己想要的算法,你可以使用一種簡單的方式,已經在Java庫中實現。

您可以創建Integer集合(排序的List)(startend,凡在你的榜樣start=1end=9),然後使用方法Collections.shuffle(list);,例如以這種方式:

static List<Integer> randArray(int start, int end) { //specify start/end 
    List<Integer> randList=new ArrayList<>(end-start+1); //create list 
    for (int k=start;k<=end;k++) { //generate integers in order 
     randList.add(k); //add integers to the list 
    }   
    Collections.shuffle(randList); //reoder randomly the list 
    return randList; //return the list with items in random order 
} 

方法shuffle只是隨機地重新排列列表中的項目。

+0

是啊,它的工作原理...雖然現在我更感興趣知道Collections.shuffle()如何工作。 – gonephishing

0

按排序順序爲數字1至9生成一個數組。

int arr[]=new int[9]; 
for(int i=0;i<9;i++) 
    arr[i]=i+1; 

現在shuffle給定的數組。

如何隨機播放數組?

To shuffle an array a of n elements (indices 0..n-1): 
    for i from n - 1 downto 1 do 
     j = random integer with 0 <= j <= i 
     exchange a[j] and a[i] 

參考

http://www.geeksforgeeks.org/shuffle-a-given-array/

+0

是的...剛剛得到這個算法 - > [Fisher-Yates_shuffle](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) – gonephishing

+0

是的,這個將隨機產生1到9的數字,相等概率。 – Jerky

0

使用Java 8中,Enne的方法可以寫成這樣:

private static List<Integer> generateRandom(int low, int high) 
{ 
    List<Integer> range = IntStream.range(low, high).boxed() 
            .collect(Collectors.toList()); 

    Collections.shuffle(range); 
    return range; 
} 
+0

我現在不使用Java 8,但這肯定有助於:) – gonephishing

0
public ArrayList<Integer> getRandom(int numbers,int min_value, int max_value) 
{  
    HashSet<Integer> list = new HashSet<>(); 
    Random r = new Random(); 
    while (list.size()<numbers) { 
     list.add(r.nextInt(max_value - min_value) + min_value); 
    } 
    return new ArrayList<>(list); 
} 

備選:

public ArrayList<Integer> getRandom(int numbers,int min_value, int max_value) 
{  
    Random r = new Random(); 
    ArrayList<Integer> list = new ArrayList<>(); 
    for(int i=min_value; i<=max_value;i++) 
     list.add(i); 
    while (list.size()>numbers) { 
     list.remove(r.nextInt(list.size())); 
    } 
    Collections.shuffle(list); 
    return list; 
} 

備選:

public ArrayList<Integer> getRandom(int numbers, int min_value, int max_value) { 
    ArrayList<Integer> list = new ArrayList<>(); 
    for (int i = min_value; i <= max_value; i++) { 
     list.add(i); 
    } 
    Collections.shuffle(list); 
    return new ArrayList<>(list.subList(0, numbers)); 
} 
+0

謝謝...所有這三種算法都可以工作。雖然如前所述,在第一種方法中,list.add()會隨着越來越多的數字被填充到HashSet中而使得進程變得更慢,因爲相同的隨機數字會一次又一次地產生。這會影響算法的效率。另外,正如其他評論中所提到的,list.remove()方法效率低下,因爲每次刪除一個數字以填補空缺時,都必須移動數字。我猜[Fisher-Yates_shuffle](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle)是一個類似於Collections.shuffle()的算法。 – gonephishing