8

我编写了一个程序来查找给定项目列表的所有可能排列。这恰恰意味着我的程序打印了 r=0 到 n 的所有可能的 P(n,r) 值

下面是代码:

package com.algorithm;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Permutations<T> {
    public static void main(String args[]) {
        Permutations<Integer> obj = new Permutations<Integer>();
        Collection<Integer> input = new ArrayList<Integer>();
        input.add(1);
        input.add(2);
        input.add(3);

        Collection<List<Integer>> output = obj.permute(input);
        int k = 0;
        Set<List<Integer>> pnr = null;
        for (int i = 0; i <= input.size(); i++) {
            pnr = new HashSet<List<Integer>>();
            for(List<Integer> integers : output){
            pnr.add(integers.subList(i, integers.size()));
            }
            k = input.size()- i;
            System.out.println("P("+input.size()+","+k+") :"+ 
            "Count ("+pnr.size()+") :- "+pnr);
        }
    }
    public Collection<List<T>> permute(Collection<T> input) {
        Collection<List<T>> output = new ArrayList<List<T>>();
        if (input.isEmpty()) {
            output.add(new ArrayList<T>());
            return output;
        }
        List<T> list = new ArrayList<T>(input);
        T head = list.get(0);
        List<T> rest = list.subList(1, list.size());
        for (List<T> permutations : permute(rest)) {
            List<List<T>> subLists = new ArrayList<List<T>>();
            for (int i = 0; i <= permutations.size(); i++) {
                List<T> subList = new ArrayList<T>();
                subList.addAll(permutations);
                subList.add(i, head);
                subLists.add(subList);
            }
            output.addAll(subLists);
        }
        return output;
    }
}

输出

P(3,3) : Count (6) :- [[1, 2, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2], [2, 1, 3], [1, 3, 2]]
P(3,2) : Count (6) :- [[3, 1], [2, 1], [3, 2], [1, 3], [2, 3], [1, 2]]
P(3,1) : Count (3) :- [[3], [1], [2]]
P(3,0) : Count (1) :- [[]]

我的问题是,当我增加输入列表中的数字时。运行时间增加,输入列表中有 11 个数字后,程序几乎死掉。运行大约需要 2 GB 内存。

我在一台有 8GB RAM 和 i5 处理器的机器上运行它,所以速度和空间不是问题。

如果有人可以帮助我编写更有效的代码,我将不胜感激。

4

4 回答 4

16

如果你不存储它——如果你只是迭代它——然后考虑使用堆算法(http://www.cut-the-knot.org/do_you_know/AllPerm.shtml上的#3 )——或者,只是为了让你的生活更轻松,使用 Guava's Collections2.permutations,它实际上并没有构建整个排列列表——它会在运行中遍历它们。(披露:我为 Guava 做出了贡献。)

于 2012-05-08T17:44:00.163 回答
8

如果您想要 15 个或更多元素的所有排列,请将它们写入磁盘或数据库或其他东西,因为它们不适合内存。编辑:Steinhaus-Johnson-Trotter 算法。这可能是您正在寻找的。

于 2012-05-08T17:37:39.720 回答
7

Google (Guava) 的 Java 库为此提供了一个实用方法:Collections2#permutations(Collection)

于 2013-07-15T14:25:23.583 回答
2

您确实意识到您正在生成非常大的列表,并且运行时间会随着列表长度的增加而增加。你确定给你带来麻烦的清单应该有多长吗?

可能对某些人有所帮助的一件事是在找到每个排列时打印它,而不是将它们全部收集到一个列表中然后打印它们。当然,如果重点是实际存储整个列表,而不仅仅是打印它们,那将无济于事。

于 2012-05-08T17:34:36.797 回答