【问题标题】:Randomizing a long array with only unique digits随机化一个只有唯一数字的长数组
【发布时间】:2018-03-14 10:19:38
【问题描述】:

我正在尝试创建一个由数字 0 - 9 以随机顺序组成的长数组,这意味着不会有相同数字的重复。我是一个新手编码员,这就是我试图想出的。

    public static void shuffle() 
{
    long[] rn = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

    Random rand = new Random();

    for (int i = 0; i < 10; i++) {
        int n;
        n = rand.nextInt(10) + 0;

        for (int j = 0; j < 10; j++) 
        {
            if (n != rn[j]) 
            {
               j++; 
            }
            else if (n == rn[j]) 
            {

                n = rand.nextInt(10) + 0;
                if (j > 0) 
                {
                    j--;
                }
            }
        }
        rn[i] = n;
    }

    for (int l = 0; l < 10; l++) 
    {
        System.out.print(rn[l]);
    }
    System.out.println();

}

据我了解,这不应该让任何重复的数字通过,但确实如此。我做错什么了吗?

PS:我不允许使用集合或数组列表。我正在使用 Ready To Program IDE,它显然不支持这些。

【问题讨论】:

  • 我尝试添加 Java 标签,因为它可以帮助您从更了解该语言的人那里获得解决方案,但您的帖子已经有 5 个标签:)
  • @versvs 好建议,改shuffle为java
  • 这些'+0;'是什么适合吗?是巫毒吗?
  • 是为了一些编码练习还是家庭作业?您是否允许在您的实现中使用 Java 集合框架?因为如果你是,最明显的就是使用 Set 来组装你的随机值
  • 从一开始就有缺陷的算法。你根本不想要随机数,你想要随机顺序的数字 0..9。所以用 0..9 填充数组,然后用简单的 Fisher-Yates shuffle shuffle 它。

标签: java arrays for-loop random


【解决方案1】:

所以第二个。它有很多缺陷。

只有在您真正知道自己在做什么时,才应该在代码中更改 for 变量。

if (n != rn[j]){
    j++; 
}

这是错误的 => 您将跳过一些元素,因为您已经在 for 循环中增加了变量。因此,在每次迭代中,您将其增加 +2。

但是因为当一个测试失败时你想从头开始检查所有其他元素,你必须在 else 部分中输入 j=-1。 为什么是-1?因为在 for 循环的最后一步中,for 循环会将其增加 1,因此您将再次从 0 开始。

j = -1;

当你改变上面的一个而不增加它时,你会遇到一个永无止境的循环。 原因是,您正在用零预填充它。你会用 10 或其他数字(不是 0-9)填充它,它不会发生。 所以一种方法是用其他数字填充数组,或者只检查你用随机数填充的前 i 个数字:

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

最后这应该可以工作:

for (int i = 0; i < 10; i++) {
    int n;
    n = rand.nextInt(10);

    for (int j = 0; j < i; j++) 
    {
        if (n == rn[j]) 
        {

            n = rand.nextInt(10);
            j = -1;
        }
    }
    rn[i] = n;
}

【讨论】:

  • 谢谢,我不知道我怎么没有注意到这一点。但是,即使我将其更改为将 j 转换为 0 而不是递减,问题仍然存在。还有什么我错过的……?
  • 是的,我查看了它发现更多的缺陷让我重写了我的解决方案。
  • 嗨,我将 else if 更改为 if,但这给了我一个越界异常,所以我将 for 循环更改为 j
  • 不知道为什么会发生这种情况,但是我向您展示了您在我的解决方案中的代码中存在的缺陷。试着理解它。在 300 次运行中,阵列中没有重复。 (计算总和来测试它,应该等于 45)
  • 你也喜欢+ 0; - 是不是一些随机巫术? :)
【解决方案2】:

你确实在做一些奇怪的事情。

  • 更改循环变量 — 大多数情况下,只有在需要一些重要的魔法时才应该修改循环变量(ij),否则,循环变量应该是一个人呆着。
  • Voodooish + 0 — 将 0 添加到值是没有意义的。

关于您的 shuffle 方法,我提出了另一种方法。你有一个循环中的一个循环,所以当数组变大时,执行时间会呈指数增长。

相反,也可以从源数组中随机选择一个索引,然后用该值填充新数组的下一个位置。当然,为了避免源数组中的某个值被选取两次,我们会将该值与源数组最后一个位置的值交换并减小其大小。

index | 0 | 1 | 2 | 3 | 4  |
value | 2 | 3 | 5 | 7 | 11 |
arraySize: 5

Step 1. Pick random index, where index is less than arraySize
(in this example index 1 has been picked)

index | 0 | 1 | 2 | 3 |  4 |
value | 2 | 3 | 5 | 7 | 11 |
arraySize: 5
pickedIndex: 1

Step 2. Swap value at pickedIndex with value at index arraySize − 1

index | 0 |  1 | 2 | 3 | 4 |
value | 2 | 11 | 5 | 7 | 3 |
arraySize: 5

Step 3. Decrease array size, so the value previously on the picked
position won't be picked again

index | 0 |  1 | 2 | 3 |
value | 2 | 11 | 5 | 7 |
array size: 4

代码如下所示:

private static int[] shuffle(int[] array) {
    int[] availableNumbers = new int[array.length];
    int availableNumbersLength = availableNumbers.length;
    System.arraycopy(array, 0, availableNumbers, 0, array.length);
    int[] shuffledArray = new int[availableNumbers.length];

    Random r = new Random();
    for (int i = 0; i < availableNumbers.length; i++) {
        int index = r.nextInt(availableNumbersLength);
        shuffledArray[i] = availableNumbers[index];
        availableNumbers[index] = availableNumbers[availableNumbersLength - 1];
        availableNumbersLength--;
    }
    return shuffledArray;
}

请注意,我复制了输入数组,以便源数组保持不变,并返回一个包含随机顺序元素的新数组。当然,您也可以对原始数组进行洗牌。

【讨论】:

  • 在第 2/3 步中,索引 1 的值应该是 5 而不是 3 对吧?否则你不会洗牌。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-27
  • 2011-02-17
  • 2012-04-29
相关资源
最近更新 更多