【问题标题】:How to generate an array of pseudo-random, unique, sorted integers without using an if statement?如何在不使用 if 语句的情况下生成伪随机、唯一、排序整数数组?
【发布时间】:2021-05-28 13:32:17
【问题描述】:

我需要创建一个伪随机唯一整数数组,这些整数已经按升序排列,而不使用 if 语句。例如:

[3,5,7,12]

到目前为止,我能够想出这段代码,它重复了一些数字并且没有将整数按排序顺序排列。

int[] arr = new int[r.nextInt(10)];
for (int i = 0; i < arr.length; i++) {
    int randInt = r.nextInt(arr.length);
    arr[i] = randInt;
}

解决此问题的最佳方法是什么? 注意: 我不能使用ArrayListsort 方法。

【问题讨论】:

标签: java arrays sorting for-loop if-statement


【解决方案1】:

您可以添加上一个随机数并添加到当前随机数以确保它大于前一个。如果你想限制随机数,那么你可以使用nextInt(int bound)。我建议使用 bound 以避免任何可能的溢出。

Random r = new Random();
int prev = r.nextInt(); // seed value may or may not be added to list.
int size = 10; // desired size of random list
int[] rands = new int[size];
int bound = 1000;

for (int i = 0; i < size; i++) {
    // this ensures that new number is always greater than the previous one
    rands[i] = (prev + 1) + r.nextInt(bound);
    prev = rand[i];
}

如果所有数字都需要在给定范围内,我们需要使用算术级数公式。 aN = a +(n-1) d。我们需要计算 d 并将其添加到之前的随机数中,以确保新的数字更大。

所以在一个正常的算术级数中,从a 开始,如果我们继续添加dn 次,那么我们肯定会达到aN。所以要生成一个随机升序序列使得最后一个数小于等于aN,我们需要添加一个小于等于d且大于0的随机数(保证序列元素的唯一性)。所以我们在每次迭代中添加nextInt(d) + 1

Random r = new Random();
int aN = 20; // desired max value
int n = 10; // desired size of random list
int[] rands = new int[n];

int seed = r.nextInt(aN / 2); // divide by 2 to ensure it is not close to aN
int d = (aN - seed) / (n - 1);
// This d would be passed to the prev random number to get the new random number.
// This ensures that that last element never crosses the max range even if
// `nextInt` returns the maximum possible value (d-1).

rands[0] = seed;
int prev = seed;
for (int i = 1; i < n; i++) {
    rands[i] = prev + r.nextInt(d) + 1;
    prev = rand[i];
}

【讨论】:

  • 哇,这真是天才!但是,如果我希望数组中的随机数在某个范围内:例如从 0 到 20,你能给我一个提示吗?像 [1,2,5,12,18, 19]
  • @dwin812 我添加了一个。但如果不使用if 条件,它就不是万无一失的。这是因为nextInt 可以返回一个非常小的数字,包括 0。因此,为了确保唯一性,我们可能需要使用 if
  • @dwin812 我已经更新了这个答案。立即查看
  • @GauthamM - 你不需要temp。你可以简单地写rands[i] = (prev + 1) + r.nextInt(bound); prev = rands[i];
  • @ArvindKumarAvinash 是的,我只是用 temp 来专注于操作
【解决方案2】:

没有ArrayListsort方法:你可以使用TreeSet,它为整数提供升序并保证唯一值:

TreeSet<Integer> set = new TreeSet<>();
while (set.size() < 10) {
    set.add((int) (1 + Math.random() * 100));
}

int[] arr = set.stream().mapToInt(Integer::intValue).toArray();

System.out.println(Arrays.toString(arr));
// [15, 20, 30, 42, 46, 55, 59, 63, 92, 98]

【讨论】:

    【解决方案3】:

    您可以使用Random 的实例并流式传输值。

    Random r = new Random();
    int min = 1;
    int max = 20_000;
    int count = 19_999;
    int[] vals =
            r.ints(min, max).distinct().limit(count).sorted().toArray();
    
    

    上面的方法在我的机器上运行得相当快,但效率不高(特别是因为在这种情况下,所有从 1 开始的整数都按排序顺序计数)。

    count &lt;= max-min 是必要的,否则它永远不会完成执行,因为最终,生成的后续值将永远不会是不同的。随着max-min - count 的增加,效率也会增加。与Pigeonhole Principle有关。

    一个更现实的例子可能是

    
    int[] vals =
            r.ints(1, 100).distinct().limit(10).sorted().toArray();
    System.out.println(Arrays.toString(vals));
    

    打印

    [9, 15, 18, 45, 68, 70, 72, 74, 95, 96]
    

    【讨论】:

      猜你喜欢
      • 2010-12-24
      • 2020-11-19
      • 1970-01-01
      • 2012-11-06
      • 1970-01-01
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      • 2010-12-09
      相关资源
      最近更新 更多