【问题标题】:Finding all possible combinations from an indeterminate amount从不确定的数量中找到所有可能的组合
【发布时间】:2020-09-08 21:21:10
【问题描述】:

给定一个列表; List<List<SomeType>> 其中内部列表可以是任何大小,外部列表是传递给函数的变量的大小,我需要找到包含元素的所有可能组合。

因为我的解释可能很糟糕,这里有一个输入和输出示例。

输入:

[
    ['a', 'b'],
    ['c', 'd', 'e', 'f'],
    ['g', 'h'],
    ['i']
]

输出:

[
    ['a', 'c', 'g', 'i'],
    ['a', 'c', 'h', 'i'],
    ['a', 'd', 'g', 'i'],
    ['a', 'd', 'h', 'i'],
    ['a', 'e', 'g', 'i'],
    ['a', 'e', 'h', 'i'],
    ['a', 'f', 'g', 'i'],
    ['a', 'f', 'h', 'i'],
    ['b', 'c', 'g', 'i'],
    ['b', 'c', 'h', 'i'],
    ['b', 'd', 'g', 'i'],
    ['b', 'd', 'h', 'i'],
    ['b', 'e', 'g', 'i'],
    ['b', 'e', 'h', 'i'],
    ['b', 'f', 'g', 'i'],
    ['b', 'f', 'h', 'i']
]

我完全不知道如何完成这项工作。我根本无法理解它,任何帮助将不胜感激。

【问题讨论】:

  • 总排列可能非常大 - 我建议编写一个迭代器生成它们而不存储它们。这很简单,你只需要一个计数器数组,外部列表的大小,然后你就可以“计数”了。增加第一个计数器 - 它是否超过第一个列表的大小?重置它并增加下一个计数器(或“进位”)。当最后一个计数器超过最后一个列表的大小时,您就完成了所有操作。
  • Guava offers this as a library function - 它是开源的。因此,您可以使用它,也可以从代码中获取灵感。

标签: java arrays list arraylist multidimensional-array


【解决方案1】:

这是我的实现。它似乎工作正常。我使用 String[][] 作为输入,但您可以根据需要更改它。

public class Main {

    /**
     * This method nests (input.length) for loops to build the desired output.
     * @param input The input, change the data type as needed
     * @param i An index used to keep track of the element we are checking within the nested for loops
     * @param output The output, again, change the data type as needed
     * @param newElementOutput A String[] used to temporarily hold the elements of each String[] in the output.
     */
    private static void runThrough(String[][] input, int i, ArrayList<String[]> output, String[] newElementOutput){

        if(i < input.length - 1){
            for(String element:input[i]){
                newElementOutput[i] = element;
                runThrough(input, i+1, output, newElementOutput);
            }
        }else if(i == input.length - 1){
            for(String element:input[i]){
                newElementOutput[i] = element;
                output.add(Arrays.copyOf(newElementOutput, input.length));  // a copy so when newOutput changes, the array added to output will stay the same since the reference is different
            }
        }
    }

    public static void getCombinations(String[][] input, boolean printTest){
        String[] newOutput = new String[input.length];
        ArrayList<String[]> output = new ArrayList<>();
        runThrough(input, 0, output, newOutput);

        // Print the results, to check that everything is as it should
        if (printTest) printResults(output);
    }

    private static void printResults(ArrayList<String[]> output){
        System.out.println("Combinations:\n");
        for(String[] test:output){
            for(String combination:test){
                System.out.print(combination);
            }
            System.out.print("\n");
        }

        /*
        Since in the given example there are four sets of 2, 4, 2 and 1 elements, respectively,
        there should be 2 * 4 * 2 * 1 = 16 different combinations
        */
        System.out.println("\nTotal number of combinations: " + output.size());
    }

    public static void main(String[] args){

        String[][] arr = {
            {"a", "b"},
            {"c", "d", "e", "f"},
            {"g", "h"},
            {"i"}};
        getCombinations(arr, true);
    }
}

【讨论】:

    【解决方案2】:

    检查一下我认为这可以解决您的问题

        public class Test {
    
            public static void main(String a[]) {
                List<List<String>> lists = Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c", "d", "e", "f"), Arrays.asList("g", "h"), Arrays.asList("i"));
                System.out.println("lists = " + lists);
                List<List<String>> out = getOutPut(new ArrayList<>(), lists);
                System.out.println("out = " + out);
            }
    
            private static List<List<String>> getOutPut(List<String> conList, List<List<String>> lists) {
                List<List<String>> out = new ArrayList<>();
                if (lists.size() == 1) {
                    lists.get(0).forEach(s -> {
                        List<String> newList = new ArrayList<>(conList);
                        newList.add(s);
                        out.add(newList);
                    });
                } else {
                    lists.get(0).forEach(s -> {
                        List<String> newList = new ArrayList<>(conList);
                        newList.add(s);
                        out.addAll(getOutPut(newList, lists.subList(1, lists.size())));
                    });
                }
                return out;
            }
        }
    

    【讨论】:

    • 我使用的数据类型为 String 但你可以用通用的方式优化它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-05
    相关资源
    最近更新 更多