【问题标题】:Permutation - Need help desining a better block that won't need unused values排列 - 需要帮助设计一个不需要未使用值的更好块
【发布时间】:2012-08-07 18:00:04
【问题描述】:

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

  • 当前排列从提供的值中获取全局最小值和最大值。但是,由于某些排列不在所需范围内,因此随后会丢弃它们。

  • 这个想法是例如有 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;
        }
    }
}

【问题讨论】:

    标签: java algorithm


    【解决方案1】:

    您的问题是将 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 数学来非常有效地执行此方法。

    【讨论】:

    • 我忘了添加排列是可重复的。因此 1、2、3、4 实际上是 256 种可能的组合。
    • 这更容易做......而不是阶乘,它将是 n^k ,即在每一步除以 n。
    • 您不需要对每个值都进行数组查找来使用这种通用方法。如果数字范围是 1-100 和 1,000,000 - 100,000,000 有两个数字,例如,使用从 0 到 (99,000,100)**2-1 的计数器,转换为 0-99,000,099 中的值。如果值
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    相关资源
    最近更新 更多