【问题标题】:Permutations of ArrayList<Integer>ArrayList<Integer> 的排列
【发布时间】:2018-04-29 19:57:10
【问题描述】:

我正在解决一个问题,我必须获得数字数组列表的所有排列。唯一的限制是任何数字都不能以 0 开头,所以如果我们有 [0,1,2] 我们将获得

[1,2,0]

[1,0,2]

[2,0,1]

[2,1,0]

我知道如何使用 3 个循环来执行此操作,但问题是我必须对不同大小的不同数字集重复此操作,所以我需要一种可以应用于不同数字集的方法,但我不知道关于如何做到这一点。我想我必须使用某种递归函数,但我不知道如何实现它,所以数字不能以 0 开头。有什么想法吗?请不要只发布我想了解问题的代码,谢谢!

【问题讨论】:

  • 分享您的实现(即使它以 0 开头),以便我们帮助您对其进行微调
  • 将排列(最好使用递归获取)放入 ArrayList。在返回 ArrayList 之前,遍历它并删除所有以 0 开头的元素。

标签: java arraylist combinations permutation


【解决方案1】:

奇怪的问题!有趣的代码kata。

我天真地认为我会有一个递归方法:

  • 调用者当前选择的项目列表
  • 一组可供被调用者使用的项目

该方法将遍历集合以再选择 1 个项目,并使用由该项目扩展的列表和由该项目减少的集合来调用自身。返回后,从列表中删除,添加回设置并继续下一项(当然要获取该设置的防御性副本)。

如果当前列表为空,则根据您的规则,选定的第一项不能为 0。如果您必须在某处收集排列(不仅仅是打印),则集合或观察者需要第三个参数。

当可用集合为空时,递归显然停止,此时排列被发送到集合或观察者。

如果项目可以重复,您可能会受益于先对它们进行排序,以便跳过在给定位置再次选择相同的项目。

请注意,对于 N 个项目,这需要 N 的递归深度。但是危险是最小的,因为即使 N=10000,它也可能不会 stackoverflow,但是完成的 CPU 时间将是 order(N!)(可能是宇宙的尽头......)

【讨论】:

    【解决方案2】:

    您可以按照此处所述递归解决此问题:Permutation of an ArrayList of numbers using recursion。 唯一缺少的是你对零的限制,这可以通过某种方式解决(循环取自上面的示例):

    for (List<Integer> al : myLists) {
    
        // The part you need to add:
        if (al.get(0) == 0) {
            continue;
        }
    
        String appender = "";
        for (Integer i : al) {
            System.out.print(appender + i);
            appender = " ";
        }
        System.out.println();
    }
    

    您基本上检查每个排列的第一个元素并跳过前导零的元素。 continue 跳转到循环的下一次迭代,因此跳转到下一个排列。

    【讨论】:

    • 所以我用它来创建所有排列,但我发现了一个问题,那就是当您提供的列表有很多数字时,组合无法存储并且程序完成,因为它超出了内存堆,因此理想的做法是计算一个排列并执行我想要执行的操作并处理该排列,因此我一次只使用一个排列,而不是将所有可能的组合存储在一个数组中。跨度>
    • 问题不在于将结果存储在数组中,而在于递归深度。每次调用函数时,返回地址都会被压入调用堆栈。这里的问题是,如果你的递归太深,因为你有一个非常大的列表,调用堆栈就会耗尽空间并且你会收到堆栈溢出。您可以使用迭代方法来计算排列,但请记住,计算所有排列的时间为 O(n!),这对于大型输入来说并不是那么有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多