【问题标题】:Issue with randomize method随机化方法的问题
【发布时间】:2014-01-29 00:39:40
【问题描述】:

我的方法不能正常工作。 该方法应该对一组数字从 1 到 20 随机排序(每个数字 必须只出现一次)。 我的问题是,当我运行程序时,一些数字会重复几次。 代码如下:

public static int randomize(int index) {

    //This array will hold the 20 numbers.
    int[] randomIndex = new int[20];

    Random ranNum = new Random();

    for (int x = 0; x<20; x++) {
        int temp;

        //The number is generated randomly and saved in temp.
        temp = ranNum.nextInt(20);

        //This loop skips the first index.
        if (x != 0){

            /*Here, the loop is supposed to compare a generated number with
            the previous one*/
            for (int y = 1; y<=x; y++) {


                while(temp == randomIndex[x-y] ) {

                    /*If the while loop finds that temp variable matches any previous                          
                    number it will generate another random number for it until it finds
                    no matches.*/
                    temp = ranNum.nextInt(20);

                }  
            }
        }

    /*Once no match has been found for temp, the number is assigned to an index, 
    and the loop is executed with a x variable increment.
    randomIndex[x] = temp;

    }
   //Finally the array with the set of random numbers is sent to the main function.
   return randomIndex[index];

  }

我得到以下输出:

19, 19, 5, 16, 6, 2, 18, 1, 15, 1, 5, 19, 11, 4, 18, 0, 5, 18, 10.

所以现在我不知道该怎么办。 :C

【问题讨论】:

  • 能否请您添加有关您的代码应该做什么的cmets?我想这对你调试也有帮助!
  • 为什么不使用List 和Collections.shuffle() 方法?
  • 或者至少将您已经绘制的每个数字添加到列表中,并使用 List.contains(newNumber) 检查它是否重复?
  • 您的主要问题是您只确保您正在使用的号码一次在列表中,这意味着您实际上并没有检查以确保它在整个列表..

标签: java algorithm sorting methods random


【解决方案1】:

当您使用Random.nextInt() 时,无法保证生成的数字是唯一的。 您应该首先生成从 1 到 20 的数字,然后将数字随机排列。现在问题变成了“如何随机打乱数字?”

或许可以参考JDKCollections.shuffle()的实现。

洗牌的算法很简单:

  1. 选择数组中的第一个元素并将其与随机位置的数字交换。
  2. 重复步骤 1 直到最后一个元素。

【讨论】:

    【解决方案2】:

    你可以通过使用这样的东西来避免它:

       final Random random = new Random();
    
    
        final HashSet<Integer> integers = new HashSet<>();
    
        while(integers.size() < 20) {
            integers.add(random.nextInt(20));
        }
    
        System.out.println(integers);
    

    【讨论】:

      【解决方案3】:

      您似乎正试图通过拒绝来生成随机数 - 也就是说,通过将每个随机数与所有以前接受的数字进行比较,然后重新生成新的,直到找到一个与所有随机数不同的随机数他们。

      正如其他人所提到的,生成从 1 到 20 的数字并用随机排列将它们打乱会更有效。但是,如果实施得当,您的方法应该会奏效……最终。

      随机 shuffle 实现可能如下所示:

      for(int i=0; i<20; i++) {  // index goes from 0..19
        randomIndex[i] = i + 1;  // value goes from 1..20
      }
      
      for(int i=0; i<20; i++) {
        int j = i + ranNum.nextInt(20 - i);  // choose random j from i <= j < 20
        int temp = randomIndex[i];           // swap elements i and j
        randomIndex[i] = randimIndex[j];
        randomIndex[j] = temp;
      }
      

      您发布的代码生成重复的原因有两个。首先,当您拒绝一个候选随机数并重新生成一个新随机数时,您需要将其与 所有 现有数字进行比较,从头开始重新启动您的内部 (y) 循环。您现有的代码不会这样做。

      其次,我相信new Random() 构造函数每次调用都会生成不同的种子。如果是这样,您的 randomize() 函数每次都会生成一个完全不同的随机列表,并从中返回选定的索引。无论如何,返回整个数组更有意义。

      【讨论】:

        【解决方案4】:

        我编辑了你的函数来生成从 1 到 20 的数组:

        public static int[] randomize() {
        
            int[] randomIndex = new int[20];
        
            Random ranNum = new Random();
            boolean isAlreadyIn;
            boolean isZero;
            int x = 0;
        
            while (x < 20) {
                isAlreadyIn = false;
                isZero = false;
                int temp;
                temp = ranNum.nextInt(21);
                for(int i = 0; i < randomIndex.length; i++){
                    if(temp == 0)
                        isZero = true;
                    if(temp == randomIndex[i])
                        isAlreadyIn = true;
                }
                if (!isZero && !isAlreadyIn){
                    randomIndex[x] = temp;
                    x++;
                }
            }
        
           return randomIndex;
        }
        

        希望对您有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-22
          • 2021-12-27
          • 2021-08-05
          • 2020-04-29
          相关资源
          最近更新 更多