2012-01-21 42 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()如果你真的想拥有一个数组。