all possible combination of n sets

前端 未结 3 1121
终归单人心
终归单人心 2021-02-06 02:47

I have n Sets. each Set has different number of elements. I would like to write an algorithm which give me all possible combinations from the sets. for example: Lets say we have

相关标签:
3条回答
  • 2021-02-06 03:15

    In the case someone wants the matrix instead of printing, I slightly modified the code:

    public class TestSetCombinations2 {
    
        public static void main(String[] args) {
            Double[] set1 = {2.0,3.0};
            Double[] set2 = {4.0,2.0,1.0};
            Double[] set3 = {3.0, 2.0, 1.0, 5.0};
            Double[] set4 = {1.0,1.0};
            Object[][] sets = {set1, set2, set3, set4};
    
            Object[][] combinations = getCombinations(sets);
    
            for (int i = 0; i < combinations.length; i++) {
                for (int j = 0; j < combinations[0].length; j++) {
                  System.out.print(combinations[i][j]+" ");
                }
                System.out.println();
            }
        }
    
        private static Object[][] getCombinations(Object[][] sets) {
    
          int[] counters = new int[sets.length];
            int count = 1;   
            int count2 = 0;
    
            for (int i = 0; i < sets.length; i++) {
              count *= sets[i].length;
            }
    
            Object[][] combinations = new Object[count][sets.length];
    
            do{
               combinations[count2++] = getCombinationString(counters, sets);
            } while(increment(counters, sets));
    
            return combinations;
        }
    
        private static Object[] getCombinationString(int[] counters, Object[][] sets) {
    
          Object[] o = new Object[counters.length];
          for(int i = 0; i<counters.length;i++) {
            o[i] = sets[i][counters[i]];
          }
          return o;
    
        }
    
        private static boolean increment(int[] counters, Object[][] sets) {
            for(int i=counters.length-1;i>=0;i--) {
                if(counters[i] < sets[i].length-1) {
                    counters[i]++;
                    return true;
                } else {
                    counters[i] = 0;
                }
            }
            return false;
        }
    }
    
    0 讨论(0)
  • 2021-02-06 03:16

    Recursion is your friend:

    public class PrintSetComb{
        public static void main(String[] args){
            String[] set1 = {"1","2"};
            String[] set2 = {"A","B","C"};
            String[] set3 = {"$", "%", "£", "!"};
            String[][] sets = {set1, set2, set3};
    
            printCombinations(sets, 0, "");
        }
    
        private static void printCombinations(String[][] sets, int n, String prefix){
            if(n >= sets.length){
                System.out.println("{"+prefix.substring(0,prefix.length()-1)+"}");
                return;
            }
            for(String s : sets[n]){
                printCombinations(sets, n+1, prefix+s+",");
            }
        }
    }
    

    In response to question from OP about generalizing it to sets of Objects:

    import java.util.Arrays;
    
    public class PrintSetComb{
    
        public static void main(String[] args){
            Integer[] set1  = {1,2};
            Float[] set2    = {2.0F,1.3F,2.8F};
            String[] set3   = {"$", "%", "£", "!"};
            Object[][] sets = {set1, set2, set3};
    
            printCombinations(sets, 0, new Object[0]);
        }
    
        private static void printCombinations(Object[][] sets, int n, Object[] prefix){
            if(n >= sets.length){
                String outp = "{";
                for(Object o: prefix){
                    outp = outp+o.toString()+",";
                }
                System.out.println(outp.substring(0,outp.length()-1)+"}");
                return;
            }
            for(Object o : sets[n]){
                Object[] newPrefix = Arrays.copyOfRange(prefix,0,prefix.length+1);
                newPrefix[newPrefix.length-1] = o;
                printCombinations(sets, n+1, newPrefix);
            }
        }
    }
    

    And finally an iterative variant. It is based on increasing an array of counters where the counter wraps and carries when it reaches the size of the set:

    import java.util.Arrays;
    
    public class PrintSetCombIterative{
    
        public static void main(String[] args){
                String[] set1 = {"1","2"};
                String[] set2 = {"A","B","C"};
                String[] set3 = {"$", "%", "£", "!"};
                Object[][] sets = {set1, set2, set3};
    
                printCombinations(sets);
        }
    
    
        private static void printCombinations(Object[][] sets){
            int[] counters = new int[sets.length];
    
            do{
               System.out.println(getCombinationString(counters, sets));
            }while(increment(counters, sets));
        }
    
        private static boolean increment(int[] counters, Object[][] sets){
                for(int i=counters.length-1;i>=0;i--){
                    if(counters[i] < sets[i].length-1){
                        counters[i]++;
                        return true;
                    } else {
                        counters[i] = 0;
                    }
                }
                return false;
        }
    
        private static String getCombinationString(int[] counters, Object[][] sets){
            String combo = "{";
            for(int i = 0; i<counters.length;i++){
                combo = combo+sets[i][counters[i]]+",";
            }
            return combo.substring(0,combo.length()-1)+"}";
    
        }
    }
    
    0 讨论(0)
  • 2021-02-06 03:32

    Great solution by krilid, I modified it a bit to return a list of all combinations.

    @Test
    public void testMap() throws Exception {
        char[] one = new char[]{'a', 'b', 'c'};
        char[] two = new char[]{'d', 'e', 'f'};
        char[] three = new char[]{'g', 'h', 'i', 'j'};
        char[][] sets = new char[][]{one, two, three};
        List<List<Character>> collector = new ArrayList<>();
        ArrayList<Character> combo = new ArrayList<>();
        combinations(collector, sets, 0, combo);
        System.out.println(collector);
    }
    
    private void combinations(List<List<Character>> collector, char[][] sets, int n, ArrayList<Character> combo) {
        if (n == sets.length) {
            collector.add(new ArrayList<>(combo));
            return;
        }
        for (char c : sets[n]) {
            combo.add(c);
            combinations(collector, sets, n + 1, combo);
            combo.remove(combo.size() - 1);
        }
    }
    
    0 讨论(0)
提交回复
热议问题