最长的Palindrome在Java中使用递归

时间:2014-06-12 22:29:50

标签: java string recursion palindrome

我试图使用递归获得字符串中最长的回文。这是我的代码:

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;。

我检查它的方式是:

An image to demonstrate

最长的回文是&#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)。

4 个答案:

答案 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/