打印给定元素数组的所有可能组合

时间:2018-05-07 01:12:44

标签: java arrays

public class TestPossibleNumbers {
public static void main(String[] args) {
    int input[] = { 1, 2, 3 };
    // int input[] = {10,11,12,13};
    possibleNumbers(input, 0);
}

public static void possibleNumbers(int[] x, int index) {
    if (index == x.length) {
        for (int i = 0; i < x.length; i++) {
            System.out.print(x[i] + " ");
        }
        System.out.println();
    }
    for (int i = index; i < x.length; i++) {
        int temp = x[index];
        x[index] = x[i];
        x[i] = temp;
        possibleNumbers(x, index + 1);

        temp = x[index];
        x[index] = x[i];
        x[i] = temp;
    }
}}

任何人都可以帮我理解for循环中的代码吗? 这个程序运行得很好。但是,我无法弄清楚它是如何工作的

3 个答案:

答案 0 :(得分:1)

您将在以下位置递归调用该方法:

 possibleNumbers(x, index + 1);

因此,该方法再次运行该方法,并传递了索引+ 1。它检查是否

if(index == x.length) 

如果陈述正确,则打印数字。

然后再次进入第二个for循环(如果if语句不正确,它仍然会输入它)。并再次调用重复方法。它将继续输入2nd for循环,但是当“index”等于或大于“i.length”时,for循环的迭代不会运行,因为你指定for循环仅在以下时间运行:

 i<i.length

当2 for循环不进行任何迭代时,该方法将停止重复出现。所以在你的情况下,当index等于3时,不会运行第二个for循环的迭代。

尝试逐步运行调试,以更深入地了解正在发生的事情。

答案 1 :(得分:0)

我会提供另一种解释,我觉得更直观。

考虑列表中只有1个数字的情况:[a]。这非常简单:只有一个组合[a]。

现在考虑列表中2个数字的情况:[a,b]。在这种情况下,您可以依次获取每个元素,然后使用前一个方法查看剩余元素的所有组合,然后再添加元素。

现在考虑列表中3个数字的情况:[a,b,c]。在这种情况下,您可以依次获取每个元素,然后使用前一个方法查看其他2个元素的所有组合,然后再添加元素。

等等3,4,5 ......元素。

因此,一般来说,请考虑列表中n个数字的情况:[a1,a2,... an]。在这种情况下,依次取出每个元素,然后使用完全相同的方法查看其他n-1个元素的所有组合,然后再添加元素。

转换为伪代码:

getCombos(values)
    for each value
        for each combo in getCombos(values with value removed)
            add value + combo to results
    return results

唯一要添加的是基本案例,这是所有递归实现所必需的。一种可能性是单个项目的情况。然而,更简单的一个:如果没有值,那么结果就是一个空列表。

因此将其转换为Java,使用集合清楚地表明元素必须是唯一的(以避免重复的结果),使用流并使其成为通用的,以便它适用于任何类型:

Stream<List<C>> combos(Set<C> values) {
    if (values.isEmpty())
        return Stream.of(new ArrayList<>());
    else
        return values.stream().flatMap(value -> 
            combos(values.stream()
                .filter(v -> !v.equals(value))
                .collect(toSet())).peek(r -> r.add(value)));
}

您的代码实际上只是同一算法的替代实现,它将所考虑的元素交换到数组的前端,而不是创建新的集合。

答案 2 :(得分:0)

程序打印数字的排列而不是组合。

排列 - 订单很重要 组合 - 顺序无关紧要,更多的是从n

中选择k个元素

例如

int a= {a,b};
permutation = {ab,ba} 
whereas combination ={{},{a},{b},{a,b}}

了解该计划的运作方式 通过以下链接将 https://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/

不要对for循环中的递归感到困惑。 if (index == x.length)是递归的终止条件。 在调用递归调用possibleNumbers之前和之后的for循环中,交换了元素。

在交换之前有助于生成所有可能的结果,并且交换元素将交换到先前的位置,以便从for循环生成所有其他排列。这可能听起来令人困惑,请通过链接。