【问题标题】:array with random ints but no duplicates and first number showing [duplicate]具有随机整数但没有重复且第一个数字显示 [重复] 的数组
【发布时间】:2021-06-24 07:16:31
【问题描述】:

这可能已经问过了,但我有点难以理解。我创建了一个 for 循环来将随机整数添加到我的数组中,但是当整数已经在数组中时,重新启动循环。但是我继续将相同的整数放入数组+当已经有重复时,数组大小会增加。有谁知道我做错了什么?

        Random r = new Random();
        int[] tes = new int[5];
        for (int i = 0; i < tes.length; i++) {
            int q = r.nextInt(10);
            for (int j = 0; j < i; j++) {
                if (q == tes[j]){
                    i=i-1;
                }
            }
            tes[i] = q;
            System.out.println(tes[i]);
        }

和输出:

【问题讨论】:

    标签: java arrays random duplicates


    【解决方案1】:

    如果你想要一个没有重复的集合,你应该使用Set:

        Random r = new Random();
        int desirableSize = 5;
        Set<Integer> uniques = new HashSet<>(desirableSize);
        while(uniques.size() < desirableSize){
            uniques.add(r.nextInt(10));
        }
        System.out.println(uniques);
    

    add 方法已经确保如果集合中已经存在一个值,则不会添加它。

    布尔加法(E e)

    如果指定的元素不存在,则将其添加到该集合中(可选操作)。

    我使用了HashSet,但是如果插入顺序对您很重要,请改用LinkedHashSet:


    正如pjs 所指出的,上述方法适用于以下情况:

    desirableSize 远小于池大小,但如果 desiredSize 是池大小的很大一部分,你会更好 关闭洗牌池并选择第一个desiredSize元素。

    如下:

    int start  = 0;
    int end = 10;
    int size = 5;
    List<Integer> collect = IntStream.rangeClosed(start, end)
            .boxed()
            .limit(size)
            .collect(Collectors.toList());
    Collections.shuffle(collect);
    System.out.println(collect);
    

    理由如下(引用pjs):

    使用基于拒绝的方案,例如重复尝试添加到 设置,预期的迭代次数为 O(poolsize * log(desirableSize)) 与 O(desirableSize) 存储的集合。 洗牌是 O(poolsize) 但需要 O(poolsize) 存储 洗牌。作为desirableSize -> poolsize,洗牌在预期中获胜 迭代并在存储上变得具有竞争力。部分改组 实现,洗牌的迭代次数是 O(desirableSize) 虽然存储量保持不变。

    或者更通俗地说,从有限的可能数字集中提取的唯一有限数字集越高,使用第二种方法就越可取。

    例如,如果一个人生成从 0 到 1000 的数字并且只对 5 个数字感兴趣,因为随机选择相同数字的概率较低,所以使用第一种方法更好。但是,如果您(相反)对 800 个数字感兴趣,那么最好生成和打乱这 1000 个数字,并从中提取 800 个唯一值。

    在内存方面,第一种方法比第二种方法更好,但性能方面取决于我们已经描述的上下文。

    【讨论】:

      【解决方案2】:

      我没有看到问题。 您的System.out.println(tes[i]); 处于循环

      您的数组只有以下整数:5,9,2,7,1

      在自己的循环中制作 println

      for (int i = 0; i < tes.length; i++) {
          System.out.println(tes[i]);
      }
      

      因为你让i=i-1;一个值被打印了很多次

      【讨论】:

      • 很好看。谢谢,
      【解决方案3】:

      我设法以不同的方式解决它:

      List<Integer> tes = new ArrayList<>(5);
      
              Random r = new Random();
      
              for (int i = 0; i < 5; i++) {
      
                  int testNummer = r.nextInt(10);
                  if(!tes.contains(testNummer)) {
                      tes.add(testNummer);
                      System.out.println(testNummer);
                  }else{
                      i=i-1;
                  }
              }
      

      这种方式效率更高,我注意到了。

      【讨论】:

        【解决方案4】:

        一些逻辑问题

        1. 当你将值存储在数组中时增加 i 变量并且不减少 i 变量只是在发现重复时打破内部循环。

        2. 当发现重复时,重新启动外循环。使用 if else 条件 试试下面的代码,为了简单理解,我在while中改变了外循环

           int i = 0;
           while(i<5)
          
           {
               int q = r.nextInt(10);
               System.out.println("random value generated"+ q );
               int j=0;
               for (;j < i; j++)
               {
                   if (q == tes[j])
                   {
          
                       System.out.println("duplicate value found"+ q );
                       break;
                   }
               }
               if(j!=i)
               {
                   continue;
               }
               else 
               {
                   if(j==i)
                   {
                       tes[i] = q;
                       i=i+1;
                   }
               }
               System.out.println("value at "+ tes[i]);
          
           }
          

        【讨论】:

          【解决方案5】:

          如果您想要一种简单的方法来生成唯一值,您可以使用流来实现。

          Random r = new Random();
          int minVal = 1;
          int upperBound = 20;
          int count = 10;
          

          只要count 小于upperBound - minVal,它就会在没有重复的情况下完成。对于具有适当范围的非常大的计数,可能需要一些时间。

          int[] unique = r.ints(minVal, upperBound).distinct().limit(count).toArray();
          System.out.println(Arrays.toString(unique));
          

          打印这样的东西。

          [14, 1, 7, 13, 5, 16, 2, 8, 12, 4]
          

          生成固定范围的随机数的一种简单方法是简单地打乱数组。

          Integer[] vals = new Integer[20];
          for (int i = 0; i < vals.length; i++) {
              vals[i] = i+1;
          }
          // Object array will be shuffle since it backs up the list.
          Collections.shuffle(Arrays.asList(vals));
          System.out.println(Arrays.toString(vals));
          

          打印类似的东西

          [7, 20, 5, 10, 17, 18, 3, 13, 11, 1, 2, 8, 4, 9, 19, 12, 15, 16, 6, 14]
          
          
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-01-05
            • 2015-01-06
            • 2012-04-29
            • 1970-01-01
            • 1970-01-01
            • 2016-03-01
            • 1970-01-01
            相关资源
            最近更新 更多