我试图使用递归获得字符串中最长的回文。这是我的代码:
public class longestPalindrome{
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please enter a string: ");
String sentence = "iprefer"; //replace with input.nextLine();
System.out.println();
longestPalindrome(sentence, sentence, 1, 1, 0, 0);
}
// 1 1 0 0
private static void longestPalindrome(String str, String ORIGINAL, int level, int possibilities, int counter, int removedChars) {
if (str.replaceAll("[^a-zA-Z]", "").toLowerCase().equals(new StringBuffer(str).reverse().toString().replaceAll("[^a-zA-Z]", "").toLowerCase()) && str.length() >= 3) {
System.out.println("The longest palindrome in the string is:" + str);
}
else if (str.length() < 3) {
System.out.println("A palindrome of three characters or more does not exist in the string.");
}
else if (possibilities < level) {
longestPalindrome(str.substring(counter, (ORIGINAL.length() - removedChars) + counter), ORIGINAL, level, ++possibilities, ++counter, removedChars);
}
else {
longestPalindrome(ORIGINAL, ORIGINAL, ++level, 0, 0, ++removedChars);
}
}
}
所以这段代码并不完全正常,我也不知道如何修复它。这是我的解释:
假设输入字符串是:&#34; iprefer&#34;。
我检查它的方式是:
最长的回文是&#34;参考&#34;在这个字符串中。
我将浏览我的代码:
将句子发送到回文函数。
if (str.replaceAll("[^a-zA-Z]", "").toLowerCase().equals(new StringBuffer(str).reverse().toString().replaceAll("[^a-zA-Z]", "").toLowerCase()) && str.length() >= 3) {
System.out.println("The longest palindrome in the string is:" + str);
}
这个if语句用于检查字符串是否是回文。我不会改变实际的字符串,因为我想要准确地返回原始字符串。我替换所有空格并使其小写,我检查它是否是回文。如果不是:
else if (str.length() < 3) {
System.out.println("A palindrome of three characters or more does not exist in the string.");
}
我检查字符串(str)是否少于3个字符。如果是这样,就不存在回文。如果长度大于或等于3个字符,我继续使用递归语句。
else if (possibilities < level) {
longestPalindrome(str.substring(counter, (ORIGINAL.length() - removedChars) + counter), ORIGINAL, level, ++possibilities, ++counter, removedChars);
}
这是解释复杂的地方。每增加一个级别,可能性的数量就会增加一个。例如,在1级,有1种可能性。在2级,有两种可能性,依此类推。因此,我们可以得出结论,可能性的数量=水平。如果可能性的数量&lt;等级,它仍然需要找到更多的可能性。所以我的递归语句发送一个子字符串,但这些是根据样本字符串的值:&#34; iprefer&#34;。等级2:1。str.substring(0,7-1 + 0)和2. str.substring(1,7-1 + 1)。它重复了这个过程。如果可能性=等级,那么:
else {
longestPalindrome(ORIGINAL, ORIGINAL, ++level, 0, 0, ++removedChars);
}
我重置了所有值,但我增加了删除字符的级别和数量。
我不确定这种解释是否有意义,但我可以澄清是否存在问题。问题是:代码没有按预期工作。我按照我认为它会执行的方式完成了代码,它在我的大脑中运行。我已经尝试使用调试器来找出问题,但我不能。我来寻求帮助。如果我的代码中有任何愚蠢的错误,我还在学习java,请原谅我。谢谢你的帮助!
编辑:这是字符串的当前输出:
iprefer
iprefer
iprefe
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 7
at java.lang.String.substring(String.java:1907)
at recursionq61.RecursionQ61.longestPalindrome(RecursionQ61.java:30)
at recursionq61.RecursionQ61.longestPalindrome(RecursionQ61.java:30)
at recursionq61.RecursionQ61.longestPalindrome(RecursionQ61.java:33)
at recursionq61.RecursionQ61.main(RecursionQ61.java:16)
Java Result: 1
编辑2:我被禁止使用循环。
编辑3:好的,所以我好像想通了。
public class RecursionQ61 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please enter a string: ");
String sentence = "i prefer pi"; //input.nextLine();
System.out.println();
longestPalindrome(sentence, sentence, 1, 1, 0, 0);
}
// 1 1 0 0
private static void longestPalindrome(String str, String ORIGINAL, int level, int possibilities, int counter, int removedChars) {
System.out.println(str);
if (str.replaceAll("[^a-zA-Z]", "").toLowerCase().equals(new StringBuffer(str).reverse().toString().replaceAll("[^a-zA-Z]", "").toLowerCase()) && str.length() >= 3) {
System.out.println("The longest palindrome in the string is:" + str);
}
else if (str.length() < 3) {
System.out.println("A palindrome of three characters or more does not exist in the string.");
}
else if (possibilities < level) {
longestPalindrome(ORIGINAL.substring(counter, (ORIGINAL.length() - removedChars) + counter), ORIGINAL, level, ++possibilities, ++counter, removedChars);
}
else {
longestPalindrome(ORIGINAL, ORIGINAL, ++level, 0, 0, ++removedChars);
}
}
}
我不得不将str.substring(counter,(str.length() - removedChars)+ counter)更改为ORIGINAL.substring(counter,(ORIGINAL.length() - removedChars)+ counter)。
答案 0 :(得分:0)
您没有说出错误是什么。我运行了你的代码,得到了一个StringIndexOutOfBoundsException异常,因为(ORIGINAL.length() - removedChars) + counter
为7,ORIGINAL =“iprefer”,counter = removedChars = 1。字符串索引从0开始。
那就是说,我认为你的方法效率低下。尝试从最长到最短的候选解决方案,尝试从最短到最长:最短的回文长度为1(单个字符)或2个(两个相同的连续字符)。给出回文P,检查前面的字符和后面的字符是否相同,如果它们都是,例如x,那么你找到了一个回文P'= xPx。继续增长回文并记住迄今为止看到的最长时间。
答案 1 :(得分:0)
我意识到这不是一个答案,因为你特别要求递归解决方案,但也许这显示了迭代解决方案的简单和优雅。
我会尝试为你准备一个优雅的递归,但它可能看起来很像这样。
private int longestPalindrome(String s, int pos) {
int delta = 1;
// Walk outward from the pos - stop when the characters do not match.
while (pos - delta > 0 && pos + delta < s.length() && s.charAt(pos - delta) == s.charAt(pos + delta)) {
delta += 1;
}
return delta;
}
private String longestPalindrome(String s) {
int longest = 0;
int longestLocation = 0;
for (int i = 0; i < s.length(); i++) {
// How long is the longest palindrome centered here.
int length = longestPalindrome(s, i);
if (length > longest) {
// Keep track of the longest.
longest = length;
longestLocation = i;
}
}
return s.substring(longestLocation - (longest - 1), longestLocation + longest);
}
public void test() {
System.out.println("Hello");
String[] tests = new String[]{"iprefer", "madamimadam", "abcdefedcbxqy"};
for (String test : tests) {
System.out.println("longestPalindrome(" + test + ")=" + longestPalindrome(test));
}
}
答案 2 :(得分:0)
我不清楚上面代码中你的方法是什么,所以我将建议一些通用的方法来编写你需要使用递归的程序。
1)使用循环编写程序并使其工作。然后你可以用一种非常机械的方式将所有循环更改为递归方法,尽管它有点单调乏味。这不能证明对递归的理解,但它对于赋值可能已经足够好了,特别是当赋值是一个递归不适合的时候。
我会抄袭一些Old Curmudgeon的代码来证明:
int delta = 1;
// Walk outward from the pos - stop when the characters do not match.
while (pos - delta > 0 && pos + delta < s.length() && s.charAt(pos - delta) == s.charAt(pos + delta)) {
delta += 1;
}
return delta;
可以变成这样一个愚蠢的递归例程:
int recursiveMethod(int delta, int pos, String s) {
if (pos - delta > 0 && pos + delta < s.length() && s.charAt(pos - delta) == s.charAt(pos + delta)) {
return recursiveMethod(delta + 1, pos, s);
} else {
return delta;
}
}
我真的不知道这是如何工作的,我所要做的就是弄清楚它基本上执行与while
循环相同的步骤。
2)递归的本质是将问题分解为更小的部分。然后,您通过解决较小的问题来解决您的问题,并使用解决方案来解决较大的问题。
我能想到的最简单的最长回文&#34;是这样的:如果你有一个字符串s
,那么:
如果s
本身就是一个回文,那么它就是s
中最长的回文;
否则,最长的回文必须包含在删除了第一个字符的s
中,或者删除了最后一个字符的s
。因此,解决这两个子串的问题,然后选择更长的解决方案。
(您还需要一个基本情况来停止递归,但由于每个长度为1的字符串都会自动满足第一个测试,因此基本情况会自行处理。)
这将解决问题,但效率非常低。您将多次解决相同的子问题。如果从s = "abcdefg"
开始,将通过两个不同的路径在"bcdef"
两次上调用递归方法,并且更小的子串将被解决更多次。在我的头顶,我认为这是一个O(2 n )或O(n * 2 n )解决方案,而一个简单的循环算法将是O( ñ 2 )。但是当你被迫使用递归来解决它不合适的问题时会发生什么。
答案 3 :(得分:0)
您可以尝试以下代码:
public class LongestPalinSubstring{
static void printSubStr(String str, int low, int high) {
System.out.println(str.substring(low, high + 1));
}
static int longestPalSubstr(String str) {
int maxLength = 1; // The result (length of LPS)
int start = 0;
int len = str.length();
int low, high;
// One by one consider every character as center
// point of even and length palindromes
for (int i = 1; i < len; ++i)
{
// Find the longest even length palindrome with
// center points as i-1 and i.
low = i - 1;
high = i;
while (low >= 0 && high < len
&& str.charAt(low) == str.charAt(high)) {
if (high - low + 1 > maxLength) {
start = low;
maxLength = high - low + 1;
}
--low;
++high;
}
// Find the longest odd length palindrome with
// center point as i
low = i - 1;
high = i + 1;
while (low >= 0 && high < len
&& str.charAt(low) == str.charAt(high)) {
if (high - low + 1 > maxLength) {
start = low;
maxLength = high - low + 1;
}
--low;
++high;
}
}
System.out.print("Longest palindrome substring is: ");
printSubStr(str, start, start + maxLength - 1);
return maxLength;
}
// Driver program to test above function
public static void main(String[] args) {
String str = "yourinputstringhere";
System.out.println("Length is: " +
longestPalSubstr(str));
}
}
来自http://www.geeksforgeeks.org/longest-palindromic-substring-set-2/