在下面的代码中,我找到了给定输入字符串的所有可能的排列,并将它们存储在列表中,然后计算它们之间的回文。这在输入字符串长度小于10时工作正常。但是当输入字符串时如果长度大于10,则需要花费大量时间来查找排列。我想知道在这里可以优化什么来获得恒定的执行时间?
private static char[] inputArray;
private static List<String> listOfpermutations = new ArrayList<>();
private static int count;
public static void main(String s[]) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String input = reader.readLine();
inputArray = input.toCharArray();
permutation(0);
for (String combination : listOfpermutations) {
if (combination.equals(new StringBuilder(combination).reverse().toString())) {
count++;
}
}
System.out.println(count);
}
public static void permutation(int start)
{
String temp = "";
if (start != 0) {
if (start == inputArray.length) {
for (int i = 0; i < start; i++) {
temp = temp + inputArray[i];
}
if (!listOfpermutations.contains(temp)) {
listOfpermutations.add(temp);
}
}
}
for (int i = start; i < inputArray.length; i++)
{
swap(start, i);
permutation(start + 1);
swap(start, i);
}
}
static void swap(int pos1, int pos2) {
char temp = inputArray[pos1];
inputArray[pos1] = inputArray[pos2];
inputArray[pos2] = temp;
}
测试输入:
答案 0 :(得分:4)
IMO这是一个数学问题,而不是算法问题。
由于您只对回文字符串的数量感兴趣,因此无需生成所有可能的排列。
计算字符串中每种类型的字符数。将字符除以2。计算该半串的排列数。这将是答案,因为字符串的另一半只是反映了这一半。
例如,如果字符串是aabbcc,则计数a = 2,计数b = 2,计数c = 2.
因此,我们将这些减半以形成abc,以6种方式对其进行置换。这将是回文的排列数。
(您需要检查字符串中的字符数是奇数还是偶数)
答案 1 :(得分:1)
你可以在运行时间方面得到显着改善,你不会产生所有的n!排列。
由于您正在寻找回文,因此您的输入数据应包含许多重复字符。您生成排列的方式将生成许多相同的排列。 (作为副作用,你会多次计算某些排列)。
相反,请在lexicographic order
中生成排列PS。此外,您可以跳过创建完整列表,但只需在完成下一个排列后立即检查回文。
PPS。事实上,Abhishek Bansal的想法相当不错。
计算字符串中每个字符的出现次数。如果可以回文, 然后所有的角色必须有偶数,除了可能只有一个。
将每个计数除以2并在除法后按字母顺序创建一个带有该计数的字符串。例如,从“abcccabaa”获取字符串“aabc”(请注意c
具有奇数,并且在新字符串中出现一次)。
从结果字符串中,生成并计算字典顺序中的所有排列。 这将是你的答案。您不需要检查回文,因为您可以通过这种方式生成所有可能的回文。每个这样的排列将代表回文的一半。整个回文将是上半部分,可能后面跟着一个具有奇数的字符的单个实例,其次是反向的上半部分。例如,前几个回文将是
"aabc" + "c" + "cbaa"
"aacb" + "c" + "bcaa"
"abac" + "c" + "caba"
答案 2 :(得分:0)
一些性能提示:
答案 3 :(得分:0)
有一种更好的方法,可以在很大程度上减少您的时间复杂度。
实施步骤: -
接下来,如果字符串的长度是偶数,则每个字符必须具有偶数(频率)。如果每个角色都没有偶数,那么它的回文排列为零。
并且,如果字符串的长度是奇数,则它们必须恰好是具有奇数(频率)的一个字符。如果最多一个元素没有奇数,则它具有零回文置换。
例如,aaabbb
字符串长度 - 6(偶数)
但是'a'和'b'字符有奇数
因此,它的回文排列为零。
e.g。 ccccddddcc
字符串长度 - 10(偶数)
所有字符'c'和'd'都有统计数字
因此,它具有回文排列。
e.g。 ccccd
字符串长度 - 5(奇数)
'c'的计数为4(偶数),'d'的计数为奇数,即1
因此,它具有回文排列。
现在,在第二点你必须知道字符串是否有回文排列,现在我们只需要找出有多少排列。
当String缩小为c6d4之类的格式并且你知道它存在排列时,你可以像这样继续:
例如c4d2 take可以减少到3个字符(因为2c和1d,因为在回文中其余字符串是相同的)它们如何排列, 所以答案是3!/(2!* 1!)= 3
例如c4e4d1可以减少到4个字符(因为2c和2e,因为在回文中,其余字符串是相同的,1d字符在它们之间),所以答案是4!/(2!* 2!)= 6.