填充数组时检查重复项

时间:2012-01-21 11:23:32

标签: java arrays random duplicate-removal

我有一个数组,我用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);
}

然而,由于某种原因,这仍然允许重复,尽管很少(约50个阵列中的1个),例如6 6 16 24 34 46。但是当我尝试通过取出随机数元素并使用30之类的数字来复制它时,我无法重现结果。出了什么问题?

4 个答案:

答案 0 :(得分: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()。这将自动处理重复数据删除和排序,并且比当前解决方案具有更好的时间复杂性。

答案 1 :(得分:4)

使用集合会更容易,例如TreeSet已排序且无重复

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

如果你真的想拥有一个数组,请使用toArray()

答案 2 :(得分: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;
    }
}

修改

仍有潜在的无限循环。

你从49个中抽取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);
}

有限循环,与原始循环相同的概率分布。遇到重复时,您只需消除预先绘制副本的可能性,而不是重试绘制。它基本上模仿了真正的乐透式画面。

答案 3 :(得分: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);
}