0

我需要帮助通过预先丢弃不需要的排列来减小排列(重要的、可重复的)大小。

  • 当前排列从提供的值中获取全局最小值和最大值。然而,一些排列随后被丢弃,因为它们不在所需的范围内。

  • 这个想法是例如有3个需要排列的数字。例如:1-3、8-10 和 5-15。当前代码将创建 1-15 的排列,即使稍后将丢弃 4-7 的值。

不幸的是,在某些情况下,不可能在 Java 中创建一个足够大的数组来包含排列结果。

在计算排列之前将这种排列更改为仅包含必要值的任何帮助将不胜感激。

置换核心:

public class PermutationCore {
    private String[] a;
    private int n;

    public PermutationCore(String[] arrayOfPossibilities, int lengthOfPermutation) {
        this.a = arrayOfPossibilities;
        this.n = lengthOfPermutation;
    }

    public String[][] getVariations() {
        int l = a.length;
        int permutations = (int) Math.pow(l, n);

        Co.println("Permutation array size: " + permutations);

        String[][] table = new String[permutations][n];

        for (int x = 0; x < n; x++) {
            int t2 = (int) Math.pow(l, x);
            for (int p1 = 0; p1 < permutations;) {
                for (int al = 0; al < l; al++) {
                    for (int p2 = 0; p2 < t2; p2++) {
                        table[p1][x] = a[al];
                        p1++;
                    }
                }
            }
        }

        return table;
    }
}

排列

public class Permutation {
    private ArrayList<Iteration> listOfIteration = new ArrayList<Iteration>();
    private boolean prepared;
    private PermutationCore permutationCore;
    private int min = Integer.MAX_VALUE;
    private int max = Integer.MIN_VALUE;
    private int count = 0;
    private String[][] arrayOfStringResults;

    public void addIteration(Iteration iteration){
        if (prepared){throw new IllegalStateException("Permuation is already prepared. Create a new instance to add new items");}
        this.listOfIteration.add(iteration);
    }

    public void prepare(){
        String[] arrayOfString;

        for (Iteration iteration : listOfIteration){
            if (iteration.end > max){max = iteration.end;}
            if (iteration.start < min){min = iteration.start;}
        }

        arrayOfString = new String[max-min+1];

        for (int i=0; i<arrayOfString.length; i++){
            arrayOfString[i] = String.valueOf(min+i);
        }

        permutationCore = new PermutationCore(arrayOfString, listOfIteration.size());

        prepared = true;

//      Co.println("Min/max: " + min + "," + max);

        arrayOfStringResults = permutationCore.getVariations();
//      ArrayTools.sort2DStringArray(arrayOfStringResults);

    }

    public boolean iterate(){
        LABEL_ITERATE_LOOP: {
            int i=0;

            if (count == arrayOfStringResults.length){
                return false;
            }

            for (Iteration iteration : listOfIteration){
                int currentValue = Integer.valueOf(arrayOfStringResults[count][i]);

                if (currentValue > iteration.end || currentValue < iteration.start){
                    //Co.println("Failed at: " + iteration.start + "," + iteration.end + " / " + currentValue);
                    count++;
                    break LABEL_ITERATE_LOOP;
                }

                iteration.current = currentValue;
                i++;
            }

            count++;
        }

        return true;
    }

    public Iteration getIteration(Object request) {
        for (Iteration iteration : listOfIteration){
            if (iteration.request == request){
                return iteration;
            }
        }

        return null;
    }

    public ArrayList<Iteration> getListOfIterations(){
        return listOfIteration;
    }

    public static class Iteration{
        private int start;
        private int end;
        private int current;
        private Object request;

        public Iteration(int start, int end, Object request){
            this.start = start;
            this.end = end;
            this.request = request;
        }

        public double getCurrentValue(){
            return this.current;
        }

        public Object getRequest(){
            return this.request;
        }
    }
}
4

1 回答 1

3

您的问题是将 k 数字从 0 排列到 (n-1),并打印 a[n] 而不是 n。:) 这就是你可以做的,以减少迭代。

另一种方法是使用 0 到 n!-1 之间的数字并找出当前排列是什么,然后打印出来。虽然它是一种较慢的方法,但以这种格式恢复操作更快 - 我们可以快速打印第 k 个排列。

假设数字是:1、2、3、4。总共有 4 个!排列 = 24,可能。要打印第 15 个(从零开始计数)排列,我们这样做:

n = 4 a = 1 2 3 4 将 15 除以 (n-1)!

我们得到 15/6 = 2,提醒 = 3。

所以排列从 a[2] = 3 开始。

a = 1 2 4 接受提醒,除以 (n-2)!

我们得到 3/2 = 1,提醒 = 1。

所以排列现在是排列,a[1] = 3, 2

a = 1 4 取提醒,除以 (n-1)!

我们得到 1/1 = 1,提醒 = 0

所以排列现在是排列,a[1] = 3, 2, 4。

直到提醒为零。打印 a[0]= 3, 2, 4, 1。

^ 这是生成任何序列的第 k 个排列的最有效方法。

您可以使用 BigInteger 数学非常有效地执行此方法。

于 2012-06-10T19:38:33.300 回答