Java 需要解释排列算法的差异吗
我目前正在研究一个问题,要求我找到第一百万个0,1,2,3,4,5,6,7,8,9的字典排列。乍一看,我想到了一个非常粗糙的解决方案,其复杂度大约为O(n^3)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 &
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);