2012-01-21 54 views
2

我有一個數組,我用6個隨機生成的數字填充。首先它會生成1到49之間的隨機數,然後根據數組中的數字進行檢查。如果發現重複,它應該再次生成一個隨機數,然後再次執行檢查。如果沒有重複,則將該數字添加到數組中。填充數組時檢查重複內容

下面的代碼:

public void populateArray() 
{ 
    for(int i = 0; i < numberLine.length; i++) 
    { 
     randomNumber = 1 + randomGen.nextInt(49); 
     for(int j = 0; j < i; j++) 
     { 
      if (numberLine[j] == randomNumber) 
      { 
       i--; 
      } 
      else 
      { 
       continue; 
      } 
     } 
     if(i >= 0) 
     { 
      numberLine[i] = randomNumber; 
     } 
     else 
     { 
      continue; 
     } 
    } 
    Arrays.sort(numberLine); 
} 

但是,由於某種原因,這仍然可以讓一個重複,雖然很少(約1 50陣列),如6 6 16 24 34 46。但是,當我嘗試通過取出隨機數字元素並使用像30這樣的數字來重複此操作時,我無法重現結果。出了什麼問題?

+0

它有一個潛在的無限循環,這可能不是你想要,看到我對如何避免這些答案的東西。 – soulcheck

+0

是的,人們建議的部分,即可以循環的'j Arcadian

+0

不是這樣。據我可以看到所有其他的解決方案先使用繪圖,測試,重複繪製相同的範圍技術。這會導致無限循環 - 繪圖範圍不會變小。你總是可能運氣不好,並且無限制地畫出相同的數字。 – soulcheck

回答

2

事實上,因爲您的域名僅限於整數1和49,最好使用布爾數組來表示數量是否已經得出之間:

public void populateArray() 
{ 
    count = 0; 
    boolean[] used = new boolean[50]; 
    while (count < 6) { 
     randomNumber = 1 + randomGen.nextInt(49); 
     if (!used[randomNumber]) ++count; 
     used[randomNumber] = true; 
    } 


    int j = 0; 
    for (int i = 1; i < used.length; ++i) { 
     numberLine[j++] = i; 
    } 
} 

編輯

仍然有潛在的無限循環。

您正在繪製6個數字,但沒有重複。正確的解決方案是:

public void populateArray() { 
    List<Integer> pool = new ArrayList<Integer>(); 
    for (int i = 0; i < 49; ++i) { 
     pool.add(i + 1); 
    } 

    for (int i = 0; i < 6; ++i) { 
     randomNumber = randomGen.nextInt(pool.size()); 
     numberLine[i] = pool.get(randomNumber); 
     pool.remove(randomNumber); 
    } 

    Arrays.sort(numberLine); 
} 

有限循環,與原始循環具有相同的概率分佈。當遇到重複時,您不必重試繪圖,而是預先消除重複繪製重複的可能性。它基本上是模擬真正的樂透抽籤。

4

以下是可能發生的情況。假設您已經繪製了12。在第三次迭代中,您再次繪製1。會發生什麼是你的內循環會減少i一次,之後numberLine[i] = randomNumber將把1放入第二個的位置。你現在在陣列中有1, 1。 QED。

已經想通了這個錯誤,我有幾個建議:

1)以下:

for(int j = 0; j < numberLine.length; j++) 

應該

for(int j = 0; j < i; j++) 

否則你看那個位置尚未填充。

2)我會重寫整個算法使用SortedSet:只需保持添加隨機數的設置,直到它有所需的大小。最後,使用toArray()。這將自動處理重複排序和排序,並且比您當前的解決方案具有更好的時間複雜性。

+0

編輯以反映建議。謝謝你,我忘了這是多麼的低效。 – Arcadian

+0

是的,但我沒有在這裏展示全班。你需要這一切嗎?如果它能幫助 – Arcadian

+0

@Arcadian,那麼它就會起作用,它實際上並不重要:它是一種「公共」方法,這意味着它可以隨時被任何人調用。例如,可以連續調用兩次。因此,是否有其他代碼爲我們清理數組是沒有意義的:數組必須被視爲任意的,不應該做出任何假設。 – alf

1

所有其他的建議都是一樣的好,這裏是一些代碼,我認爲應該工作:

public void populateArray() 
{ 
    boolean OK = true; 
    int i = 0; 
    while (i < numberLine.length) 
    { 
     randomNumber = 1 + randomGen.nextInt(49); 
     for(int j = 0; j < i; j++) if (numberLine[j] == randomNumber) OK = false; 
     if (OK) 
     { 
      numberLine[i] = randomNumber; 
      i++; 
     } 
     OK = true; 
    } 
    Arrays.sort(numberLine); 
} 
+1

好的,我遵循你在這裏做的,使用布爾標誌。但是,假設該標誌是錯誤的,這意味着該數字不會被添加到數組中,但是由於具有i ++的for循環,是不是意味着它仍然會移動到下一個數組元素? – Arcadian

+0

好點,看我的編輯。 –

+0

試過了,似乎仍然無限循環。我相信這是因爲'j Arcadian

4

這將是更容易集合了很多,例如TreeSet這既是排序並沒有重複

Set<Integer> set = new TreeSet<Integer>(); 
while (set.length() < 6) { 
    set.add(randomGen.nextInt(49)); 
} 

之後使用toArray()如果你真的想擁有一個數組。