从矩阵中找出长度为N的组合,每个元素需要来自不同的行/列

时间:2016-01-11 22:12:29

标签: java algorithm backtracking

在n * n矩阵中,找到长度为n的所有组合,使得组合中的每个元素来自不同的列和不同的行。

For 2*2 Matrix
00 01
10 10
The possible combinations are (00,10) and (10,01)

For 3*3 Matrix
00 01 02
10 11 12
20 21 22
The possible combinations are (00,11,22) (00,12,21) (10,01,22) (10,02,21) (20,01,12) (20,02,11) 

我在java中编写了以下代码。该程序创建长度为n的所有组合。

对于2 * 2矩阵,程序返回长度为2的所有组合。即4 * 4 = 16个组合
[[0,0],[0,1],[0,10],[0,11],[1,0],[1,1],[1,10],[1,11],[ 10,0],[10,1],[10,10],[10,11],[11,0],[11,1],[11,10],[11,11]]

我想修改这个程序,只需要返回满足上述属性的唯一组合。

我已尝试对for循环进行多次修改(如下所示)。但他们都没有工作。

for (int j = 0; j < lengOfComb; j++)

注意:传递给函数findCombinations的ar,j是多余的 我将此article称为代码。

import java.util.ArrayList;

public class MatrixCombinations {

    public static void main(String args[]) {
        int n = 4;
        int[][] multi = new int[n][n];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                multi[i][j] = i * 10 + j;
            }
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(multi[i][j] + " ");
            }
            System.out.println();
        }

        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> current = new ArrayList<Integer>();
        findCombinations(multi, result, current, 0, 0, 0);
        System.out.println(result);
        System.out.println("The lenght of the result array is " + result.size());

    }

    public static void findCombinations(int[][] input, ArrayList<ArrayList<Integer>> result, ArrayList<Integer> current,
            int lengOfComb, int m, int n) {
        int size = input.length;

        if (lengOfComb == size) {
            ArrayList<Integer> temp = new ArrayList<Integer>(current);
            result.add(temp);
            return;
        }

        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                current.add(input[i][j]);
                findCombinations(input, result, current, lengOfComb + 1, i, j);
                current.remove(current.size() - 1);
            }
        }
    }

}

1 个答案:

答案 0 :(得分:1)

你的方法很复杂 基本上这个问题也可以用这种方式表达:
查找范围[0 , n)中数字长度n的所有排列。然后,通过将具有范围[0 , n)的排列组合成一组对,可以将这些排列转换为搜索的组合,这些对可以用作矩阵中的索引:

int[] permutation = generatePermutation(int n);
int[] combination = new int[n];

for(int i = 0 ; i < n ; i++)
    combination[i] = matrix[i][permutation[i]];

基本上,您需要做的就是生成[0 , n)中数字的所有排列,并应用上述算法来查找排列:

编辑:对不正确的排列发生器感到抱歉,当我发布这个时,我有点心烦意乱,匆忙。这是使用Steinhaus-Johnson-Trotter算法的正确生成器:

void generatePermutations(List<Integer> permutation , int n){
    if(n == -1){
        for(int i = 0 ; i < permutation.size() ; i++)
            System.out.print(matrix[i][permutation.get(i)]);
        System.out.println();
    }else{
        for(int i = 0 ; i <= permutation.size() ; i++){
            permutation.add(i , n);
            generatePermutations(permutation , n - 1);
            permutation.remove(i);
        }
    }
}

使用此矩阵进行试运行:

matrix = new String[][]{
    {"a1" , "b1" , "c1"} ,
    {"a2" , "b2" , "c2"} ,
    {"a3" , "b3" , "c3"}
};

生成此输出:

  

A1B2C3
  b1a2c3
  b1c2a3
  a1c2b3
  c1a2b3
  c1b2a3