【问题标题】:Number of elements combinations from 2D array are possible?二维数组中的元素组合数量是可能的吗?
【发布时间】:2014-04-06 10:29:46
【问题描述】:

我有 5x5 元素表。假设该表中的每一行都是一个罐子。行中的每个元素都是罐子中不同颜色的球。 我们从第一个罐子里拿一个球,从第二个罐子里拿一个球,从第三个罐子里拿一个球……以此类推到第五罐子。 我们有 5 种球的颜色组合……然后我们把球放回相关的罐子里。 问题:有多少种组合变体是可能的? 回答 n ^ n ,其中 n 是表格大小!

问题是,我永远不知道表有多大,尽管总是对称 (n x n) 元素。我想编写 UNIVERSAL 方法,它将返回所有可能的颜色组合。

对于表格 5x5 元素,它看起来像这样:

private int combinations = 0;
private char table[][] = { {'A','B','C','D','E'},
                           {'F','G','H','I','J'}, 
                           {'K','L','M','N','O'},
                           {'P','Q','R','S','T'},
                           {'U','V','X','Y','Z'}};  

public Prog() {     

    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            for (int k= 0; k < 5; k++) {
                for (int l = 0; l < 5; l++) {
                    for (int m = 0; m < 5; m++) {

                        System.out.println(table[0][i] +" " + table[1][j]+ " " + table[2][k]+ " " + table[3][l]+ " " + table[4][m]);                            
                        combinations++;
                    }
                    System.out.println("--------------");
                }                   
            }
        }           
    }       
    System.out.println("Total combination is : " + combinations);   
}

... 但以上代码仅适用于 5x5 表格。如果我得到 4x4 或 3x3,我需要修改所有 for 循环才能正常工作...... 有人可以帮我写一个可以根据表格大小修改自身并返回正确组合的方法吗?

谢谢!!

【问题讨论】:

  • 如果目标是确定组合的数量,那么只需应用幂:a^a。如果您想要组合本身,则需要递归。
  • 使用.length开始
  • 递归应该以更易读的方式解决这个问题
  • @weston 我坚信你想创建一个迭代实现...... :)
  • @TheConstructor 我的午餐已经准备好了,所以我放弃了,但我现在有了!

标签: java arrays


【解决方案1】:

这个问题的递归解法:

import java.math.BigInteger;
import java.util.Arrays;

/**
 * Created for http://stackoverflow.com/q/22892808/1266906
 */
public class Combinations {

    public static BigInteger printCombinationsRecursively(char[][] table) {
        return printCombinationsRecursively(table, new char[table.length], 0);
    }

    public static BigInteger printCombinationsRecursively(char[][] table, char[] selection, int currentRow) {
        if(currentRow >= table.length) {
            System.out.println(Arrays.toString(selection));
            return BigInteger.ONE;
        }
        BigInteger count = BigInteger.ZERO;
        for (char c : table[currentRow]) {
            selection[currentRow] = c;
            count = count.add(printCombinationsRecursively(table, selection, currentRow + 1));
        }
        return count;
    }

    public static void main(String[] args) {
        char[][] table = new char[][] {
                new char[] {'A', 'B', 'C', 'D'},
                new char[] {'E', 'F', 'G', 'H'},
                new char[] {'I', 'J', 'K', 'L'},
                new char[] {'M', 'N', 'O', 'P'}
        };
        final BigInteger combinations = printCombinationsRecursively(table);
        System.out.println(combinations + " combinations");
    }
}

【讨论】:

  • 你不觉得方桌的组合数永远都是table.length "to the power" table.length吗?您的程序虽然是正确的,但如果您只打印递归调用中的组合,则可以进一步改进程序,当一切都完成后,使用BigIntegerpow() 方法计算组合的数量。
  • @AmanAgnihotri 是的,甚至 OP 在介绍中也提到它是 n^n。我只是在模仿 OP 对 5x5 表的解决方案的行为。当然,在递归中省略 count 也会提高性能。
  • 所以我在想你是否愿意这样做。 :) 不过,+1。
  • @AmanAgnihotri 我对此很好。这样,它也适用于每行具有不同数量元素的数组,例如new char[][] { new char[] {'A', 'B', 'C', 'D'}, new char[] {'E', 'F', 'G'}, new char[] {'H', 'I'}, new char[] {'J'} }。当然,如果一行没有元素,则返回BigInteger.ZERO,如果是new char[0][0],则返回BigInteger.ONE,并与[] 组合。我认为这是最接近数学组合的,你可以用这么几行得到;-)
  • 我明白你为什么认为你应该选择BigInteger。但是您是否考虑过对所有 long 进行简单的 for 循环需要多长时间?即for(long l=0;l&lt;Long.MAX_VALUE;l++) 我的意思是,如果您将其限制为 long,则此代码可能需要 才能运行。所以如果问题需要BigInteger,他们肯定需要不同的解决方案。
【解决方案2】:

5x5 数组具有相同输出的迭代版本:

void Prog() {
    int baseN = table.length;
    int maxDigits = table[0].length;
    int max = (int) Math.pow(baseN, maxDigits);
    // each iteration of this loop is another unique permutation
    for (int i = 0; i < max; i++) {
        int[] digits = new int[maxDigits];
        int value = i;
        int place = digits.length - 1;
        while (value > 0) {
            int thisdigit = value % baseN;
            value /= baseN;
            digits[place--] = thisdigit;
        }

        int tableIdx = 0;
        for (int digitIdx = 0; digitIdx < digits.length; digitIdx++) {
            int digit = digits[digitIdx];
            System.out.print(table[tableIdx][digit] + " ");
            tableIdx++;
        }
        System.out.println();
        combinations++;
        if (i % maxDigits == maxDigits - 1)
            System.out.println("--------------");
    }
    System.out.println("Total combination is : " + combinations);
}

这是基于我的回答 https://stackoverflow.com/a/9315076/360211,我将其视为 5 位数字,以 5 为基数。

请注意,因为我使用int 表示max,而您将它用于combinations,因此限制为9x9 数组,因为10^10 &gt; Integer.MAX_VALUElong 最多可以提供 15x15,但这需要 才能运行!!!

【讨论】:

    【解决方案3】:

    使用数组的.length字段来确定表的大小:

    for (int i = 0; i < table.length; i++) {
        (..)
    

    此字段始终包含正确大小的数组。

    【讨论】:

    • 你还需要table.length循环
    • 那是什么意思?
    • 这是一个方桌,你从每一行中选择一个条目
    【解决方案4】:

    我认为这些方法不是非常理想,这是从 NxN 表中获取排列的一般方法。这是在 Javascript 中,但给出了方法的想法

    var table = [ ['A','B','C','D','E'],
                  ['F','G','H','I','J'],
                  ['K','L','M','N','O'],
                  ['P','Q','R','S','T'],
                  ['U','V','X','Y','Z']];
    
    
    function perm(l) {
        var n = Math.pow(l.length,l.length);
        for(var i=0; i < n; i++) {
            var s = '';
            var m = i;
            for(var k=0 ; k < l.length; k++) {
                var p = m % 5;
                s += l[k][p];
                m = ~~(m / 5);
            }
            console.log(s);
        }
    }
    
    perm(table);
    

    【讨论】:

      【解决方案5】:

      这是一个可读且易于解决的解决方案:让我们将其视为具有 n 位的 n 基数。

      假设您有一个存储数字(可能的颜色)的数组。在这种情况下,您可以通过这种方式生成排列(而不是组合)(代码未经测试):

      public int[] nextPermutation(int[] input, int base) {
          if (input == null) {
              int[] returnValue = new int[base];
          }
      
          int modulo = 1;
          for (int digitIndex = 0; (modulo > 0) && (digitIndex < input.length); digitIndex++) {
              input[digitIndex] = (input[digitIndex] + 1) % base;
              modulo = ((input[digitIndex] > 0) ? (1) : (0));
          }
      
          return ((modulo == 0) ? (input) : (null));
      }
      
      public int[] getColorByPermutation(int[] permutation, int[] colors) {
          int[] result = new int[permutation.length];
          for (int permutationIndex = 0; permutationIndex < permutation.length; permutation++) {
              result = colors[permutation[permutationIndex]];
          }
      }
      
      public void generatePermutations(int base, int[] colors) {
          int permutation = nextPermutation(null, base);
          while (permutation != null) {
              int[] currentColors = getColorByPermutation(permutation, colors);
              //Do whatever you need with the colors
              permutation = nextPermutation(permutation, base);
          }
      }
      

      【讨论】:

        【解决方案6】:

        不幸的是,我只知道 Python,但我认为以下两种解决方案可以满足您的需求。

        递归

        class Permutations:
            def __init__(self, matrix):
                self.matrix = matrix
                self.n = len(matrix)
                self.permutations(self.n)
                print('There are {} permutations!'.format(self.n**self.n))
        
            def permutations(self, count, sequence=[]):
                if count == 0:
                    chars = [self.matrix[i][sequence[i]] for i in range(self.n)]
                    print(' '.join(chars))
                    return None
                for x in range(self.n):
                    self.permutations(count-1, sequence+[x])
                if count == 1:
                    print('---------------')
        

        迭代

        def decimal_to_base_n(decimal, base):
            digits = []
            while decimal:
                digit = decimal%base
                digits.append(digit)
                decimal //= base
            digits += [0]*(base-len(digits))
            return digits[::-1]
        
        def permutations(matrix):
            n = len(matrix)
            for i in range(n**n):
                sequence = decimal_to_base_n(i, n)
                chars = [matrix[j][sequence[j]] for j in range(n)]
                print(' '.join(chars))
                if i%n == n-1:
                    print('---------------')
            print('There are {} permutations!'.format(n**n))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-25
          • 2021-07-10
          • 2023-03-20
          • 2019-04-18
          • 1970-01-01
          • 2022-01-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多