【问题标题】:generating unique row and column in 2 dimensional array在二维数组中生成唯一的行和列
【发布时间】:2015-12-23 11:34:48
【问题描述】:

我正在随机填充一个二维数组,但我希望在每一行和每一列中生成的数字都是唯一的。这是我使用的代码

int[][] values = new int[3][3];

    Random randomGenerator = new Random();
    for (int i = 0; i < values.length; i++) {

        int[] sub = values[i];
        for (int x = 0; x < sub.length; x++) {
            sub[x]= randomGenerator.nextInt(4);;
        System.out.print(sub[x] + " ");
        }
        System.out.println();
    }

我当前的输出是,这可能会改变,因为生成的数字是随机的

2 2 2 
3 2 0 
0 2 1 

但我期待这样的事情

1 2 3 
3 1 2 
2 3 1 

【问题讨论】:

  • 这个输出看起来像我对这段代码的期望。它是纯(伪)随机......
  • 我知道,我想给它设置一些条件,以便我可以重新生成它,以防行或列中存在重复。
  • @AND 您将使用的最大可能的 2D 数组大小是多少?只有 3 x 3?
  • 我正在计划 9 x 9 并计划随机生成从 1 到 9 的数字。
  • @AND 好消息,我刚刚尝试用蛮力方法对其进行编码,生成 9x9 唯一矩阵只用了不到 1 秒。如果您希望我发布我的代码,请告诉我。

标签: java arrays random


【解决方案1】:

在我看来,您正在尝试创建一个类似于数独板的矩阵,只是您没有要求检查每个单独的 3x3 子矩阵。

如果您计划使用 9x9 矩阵。您不太可能对所有 81 个元素使用 random。 (可以,但生成板所需的时间可能比需要的长得多)。

这是你可以做的:

  • 创建2个数组用于跟踪当前行/列是否已经有1-9
  • 创建一组可供选择的数字(数字范围遵循矩阵大小)
  • 第一行随机填1-9。
  • 通过检查是否可以填充,用数字递归填充空框。
  • 填写数字时,将其从数字集中删除
  • 如果有冲突,回溯到最后一个已知的好位置并继续

【讨论】:

    【解决方案2】:

    我用蛮力方法尝试了这个问题,它有效。 生成一个独特的 9 x 9 板用了不到 1 秒

    输出:

    1 2 3 4 5 6 7 8 9 
    2 6 8 9 7 4 1 3 5 
    6 3 5 7 9 1 2 4 8 
    9 5 4 8 6 2 3 1 7 
    5 4 7 1 2 8 9 6 3 
    8 1 9 6 3 7 5 2 4 
    4 9 2 3 8 5 6 7 1 
    7 8 6 5 1 3 4 9 2 
    3 7 1 2 4 9 8 5 6
    

    以下是我的代码:

    public static void main(String[] args){
        int size = 9;
    
        int[][] board= new int[size][size];
        board[0] = Util.createOrderedArray(size, 1);
    
        for(int x=1; x<size; x++){          
            board[x] = Util.createOrderedArray(size, 1);
            do{
                Util.shuffle(board[x]);
            }while(!Util.compare2DArray(board[x], board, 0, x));        
        }       
        Util.print(board);  
    }
    

    我在一个自定义的 Util 类中编写了所有的辅助方法。

    final class Util
    {
        public static void shuffle(int[] num){
            Random rnd = new Random();
            for(int x=0; x<num.length; x++)
                swap(num, x, rnd.nextInt(num.length));
        }
    
        public static void swap(int[] num, int a, int b){
            int temp = num[a];
            num[a] = num[b];
            num[b] = temp;
        }
    
        public static int[] createOrderedArray(int size, int startValue){
            int[] num = new int[size];
            for(int x=0; x<num.length; x++)
                num[x] = x+startValue;      
            return num;
        }
    
        //Return TRUE if array vs arrays is COMPLETELY different
        public static boolean compare2DArray(int[] num1, int[][] num2, int start, int end){
            for(int x=start; x<end; x++)
                if(!compareArray(num1, num2[x]))
                    return false;
            return true;        
        }
    
        //Return TRUE if arrays are COMPLETELY different 
        public static boolean compareArray(int[] num1, int[] num2){
            if(num1.length != num2.length)
                return false;
            for(int x=0; x<num1.length; x++)
                if(num1[x] == num2[x])
                    return false;
            return true;        
        }
    
        public static void print(int[][] num){
            for(int x=0; x<num.length; x++){
                for(int y=0; y<num[0].length; y++)
                    System.out.print(num[x][y] + " ");
                System.out.println(""); 
            }                           
        }
    }
    

    这是通过蛮力方法完成的。如果你想优雅地做,我们递归做会更有效率,所以不会浪费不必要的循环。

    【讨论】:

    • 备注: 我创建的 Util 类很灵活。您可以执行 Util.shuffle(board[0]); 以便不再对第一行进行排序。您还可以创建不同大小的矩阵。但是,大小超过 10 的矩阵可能需要更长的时间来处理。
    【解决方案3】:

    这是一种方法。

    您可以跟踪已生成的数字,如果再次生成则忽略它们。

    我使用Set,因为它不允许重复值。但我相信任何其他 Collections 都可以做到这一点。

    int[][] values = new int[3][3];
    
    Random randomGenerator = new Random();
    for (int i = 0; i < values.length; i++) {
        Set<Integer> set= new HashSet<Integer>();
        int[] sub = values[i];
        for (int x = 0; x < sub.length;) {
            int next= randomGenerator.nextInt(4) + 1;// +1 ensure a number in {1,2,3}
    
            if(!set.contains){
              sub[x]= next;
              set.add(next);
              x++;  //note we only add the variable if non-duplicate values were generated.
              System.out.print(sub[x] + " ");
            }
    
        }
        System.out.println();
    }
    

    注意,

    如果您尝试更改数组的大小,最好更改

    int next= randomGenerator.nextInt(4) + 1; 
    

    int next= randomGenerator.nextInt(values[i].length) + 1;
    

    因此它确保您始终有足够的distinct 号码来生成

    【讨论】:

    • 我认为必须遵循“set.contains”。我们应该在它之后反对
    • @AND 抱​​歉,我忘了在它前面添加!(所以如果它包含doesn't)。我已经编辑了答案,你
    • @nafas 我认为这个解决方案有一个潜在的问题。当row1有1,2,3时,如何防止row2变成2,1,3
    • @user3437460 看看想要的输出mate,row2确实可以变成2,1,3
    • @nafas 如果 row1 是 1,2,3 而 row2 是 2,1,3。最后一列不再是唯一的。 3 在最后一列重复。
    猜你喜欢
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多