Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 需要解释排列算法的差异吗_Java_Algorithm_Complexity Theory_Permutation - Fatal编程技术网

Java 需要解释排列算法的差异吗

Java 需要解释排列算法的差异吗,java,algorithm,complexity-theory,permutation,Java,Algorithm,Complexity Theory,Permutation,我目前正在研究一个问题,要求我找到第一百万个0,1,2,3,4,5,6,7,8,9的字典排列。乍一看,我想到了一个非常粗糙的解决方案,其复杂度大约为O(n^3) public static String permute(char[] a){ ArrayList<String> array = new ArrayList<String>(); int counter = 1; for (int i = 0; i &

我目前正在研究一个问题,要求我找到第一百万个0,1,2,3,4,5,6,7,8,9的字典排列。乍一看,我想到了一个非常粗糙的解决方案,其复杂度大约为O(n^3)

    public static String permute(char[] a){
        ArrayList<String> array = new ArrayList<String>(); 
        int counter = 1; 
        for (int i = 0; i < a.length; i++){
            array[counter] += a[i];
            for (int j = 0; j < i; j++){
            array[counter] += a[j];
                for(int k = a.length; k > i; k--){
                array[counter] += a[k];}counter++;}
        }
    }
公共静态字符串排列(char[]a){
ArrayList数组=新的ArrayList();
int计数器=1;
for(int i=0;ii;k--){
数组[counter]+=a[k];}计数器+++;}
}
}
代码可能并不完美,但其思想是选择一个数字,然后移动到数组的末尾。第二个数组创建选定数字后面的数字,第三个数组创建选定数字后面的数字。这似乎是一个糟糕的算法,我记得以前的算法是这样的

    public static HashSet<String> Permute(String toPermute) {
        HashSet<String> set = new HashSet<String>();
        if (toPermute.length() <= 1 )
            set.add(toPermute);
        else {
            for (int i = 0; i < toPermute.length(); i++ )
                for (String s: Permute(toPermute.substring(0,i)+ toPermute.substring(i+1)))
                {
                    set.add(toPermute.substring(i,i+1)+s);}
        }
        return set;
    }

}
公共静态哈希集排列(字符串toPermute){
HashSet=newhashset();

如果(toPermute.length()在我看来,(1)哪种排列是第一百万种完全取决于您使用的顺序,(2)这种排列对于递归来说是成熟的问题。我会将其作为递归程序编写,并增加每次迭代的计数。[这是您的问题吗?我真的没有看到问题…]

关于上述代码,有几点是一般性的:

  • 您应该实现接口而不是具体的类,即
    列表数组=…
  • 数组从索引0开始,计数器从索引1开始

  • 最后,要回答您的问题,有一种蛮力方法和一种更优雅的方法,它使用了数学中的一些原理。看看这一点,它解释了这些方法。

    这里有一个更有效的解决方案:

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class P24 {
    
        static final int digits[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        static List<Integer> remainedDigits = new ArrayList(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
        static final int factorials[] = new int[digits.length + 1];
        static final int N = 1000_000;
    
        static int low = -1;
        static int lowIndex = -1;
        static int highIndex = -1;
    
        public static void main(String args[]) {
            populateFactorials(digits.length);
            validateN(N);
            identifyMargins();
            int n = N;  // it will be changed
    
            int fixedDigits = digits.length - highIndex;
    
            String result = "";
            for (int i = 0; i < fixedDigits; i++) {
                result += remainedDigits.get(0);
                remainedDigits.remove(0);
            }
    
            for (int i = fixedDigits; i < digits.length; i++) {
                int pos = 0;
                int firstDigit = remainedDigits.get(pos);
                low = factorials[lowIndex];
                while (n - low > 0) {
                    pos++;
                    n -= low;
                }
                lowIndex--;
                result += remainedDigits.get(pos);
                remainedDigits.remove(pos);
            }
    
            System.out.println(result);
        }
    
        private static void validateN(int n) {
            if (n < 0 || n > factorials[factorials.length - 1]) {
                System.out.println("The input number is not valid");
                System.exit(0);
            }
        }
    
        private static void identifyMargins() {
            for (int i = 0; i < factorials.length - 1; i++) {
                if (factorials[i] <= N && N < factorials[i + 1]) {
                    lowIndex = i;
                    highIndex = i + 1;
                }
            }
        }
    
        private static void populateFactorials(int max) {
            for (int i = 0; i <= max; i++) {
                factorials[i] = fact(i);
            }
        }
    
        private static int fact(int x) {
            if (x == 0 || x == 1) {
                return 1;
            }
            int p = 1;
            for (int i = 2; i <= x; i++) {
                p *= i;
            }
            return p;
        }
    
    }
    
    不能从列表中删除元素。
    `

    谢谢,这是有用的信息,但我正试图通过应用程序了解哈希集和递归复杂性。我想知道如何应用哈希集算法来解决此排列(0123456789)。深入了解该算法的复杂性和更大规模的递归也会很好。完整的答案将是一种享受,它将向我展示两种算法在问题背景下的差异。谢谢,我实际上正在研究同一个问题,但更多的是关于旅程,而不是目标,对吗?谢谢你的输入Only从1开始,因为它是第一个排列而不是第零个排列。但是,你的问题是什么?如果是如何排序,那么不要使用字符串,而是在集合中使用整数。将实现从HashSet更改为TreeSet,它是有序的。但是速度会很慢。好的,非常感谢!我将查看TreeSet并将其与由project euler提供的快速算法。
    static List<Integer> remainedDigits = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);