Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.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_String_Recursion_Palindrome - Fatal编程技术网

Java中使用递归的最长回文

Java中使用递归的最长回文,java,string,recursion,palindrome,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";

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

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);
        }
    }
}
此if语句用于检查字符串是否为回文。我不更改实际字符串,因为我希望完全返回原始字符串。我替换所有空格并使其小写,然后检查它是否是回文。如果没有:

 else if (str.length() < 3) {
      System.out.println("A palindrome of three characters or more does not exist in the string.");
 }
我重置了所有值,但增加了级别和删除的字符数

我不确定这种解释是否有意义,但我可以澄清是否存在问题。问题是:代码没有按预期工作。我已经按照我认为它将在我的大脑中执行的方式完成了代码。我尝试过使用调试器来解决问题,但我做不到。我是来寻求帮助的。我还在学习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.substringcounter、str.length-removedChars+计数器更改为ORIGINAL.substringcounter、ORIGINAL.length-removedChars+计数器。

您没有说明错误是什么。我运行了您的代码,得到了StringIndexOutOfBoundsException异常,因为ORIGINAL.length-removedChars+计数器为7,ORIGINAL=iprefere,counter=removedChars=1。字符串索引从0开始


也就是说,我认为你的方法是低效的。与其从最长到最短测试候选答案,不如尝试从最短到最长:最短回文长度为1个单个字符或2个相同的连续字符。给定一个回文P,检查前后字符是否相同,如果它们都是,比如说,x,那么您会发现一个回文P'=xPx。继续增加回文,记住迄今为止你见过的最长回文

我意识到这不是一个答案,因为您特别要求递归解决方案,但这可能表明迭代解决方案是多么简单和优雅

我将尝试为您创建一个优雅的递归,但它可能看起来非常像这样

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

    }

}

我不清楚在上面的代码中您的方法是什么,所以我将建议一些通用的方法来编写需要使用递归的程序

我使用循环编写程序并使其工作。然后,您可以以一种相当机械的方式将所有循环更改为递归方法,尽管这有点单调乏味。这不会说明对递归的理解,但对于赋值来说可能已经足够好了,尤其是当赋值一开始就不适合递归的时候

我将剽窃一些老顽皮鬼的代码来演示:

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循环相同

递归的本质是将问题分解成更小的部分。然后你通过解决较小的问题来解决你的问题,并使用这些较小问题的解决方案来确定较大问题的解决方案

我能想到的最长回文的最简单方法是:如果你有一个字符串s,那么:

如果s本身是回文,那么它是s中最长的回文

否则,最长回文必须包含在删除第一个字符的s中,或者包含删除最后一个字符的s中。因此,解决这两个子串的问题,然后选择较长的解决方案

您还需要一个基本情况来停止递归,但是由于长度为1的每个字符串都自动满足第一个测试,因此基本情况本身处理起来很简单


这将解决问题,但效率很低。您将多次解决相同的子问题。如果从s=abcdefg开始,递归方法将通过两个不同的路径对bcdef调用两次,更小的子字符串将被求解更多次。在我脑海中,我认为这是一个O2n或On*2n的解决方案,而一个简单的循环算法将是On2。但当你被迫使用递归来解决不合适的问题时,就会发生这种情况

您可以尝试以下代码:

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));
}
}


什么是示例输出?发生了什么事不是你想要的?再解释一下。我听不懂你的解释。我的建议是:在longestPalindrome的开头放一个System.out.println,以打印出参数的当前值。基于此,您可以确定调用它的字符串是否是您认为应该是的字符串,然后您可以确定您的整个方法是错误的,还是您在做其他错误的事情。我最初的尝试表明它在递归地调用wit
h iprefe,意思是你已经丢失了回文。好的,我会编辑这个问题。我想你的导师告诉过你必须使用递归?这对于递归来说确实不是一个好问题;这种情况下,尝试使用递归会使问题比非递归方法复杂10倍。这是编程类中经常出现的问题,我不知道该怎么办。@ajb hmmm。。。由于某种原因,这根绳子很细。我正在更新问题嗯。。。那么我必须做什么呢:ORIGINAL.length-removedChars+counter-1?我理解,但我仍然不明白为什么输出字符串如此奇怪。@AkshayPathak你说的是以异常开头的输出吗?这不是一个输出字符串,这是一个堆栈跟踪,这意味着你的程序抛出了一个异常。堆栈跟踪显示,在程序的第30行,您试图使用一个子字符串,其中一个子字符串参数超出了字符串的界限。是的,我知道您在说什么,只有前3个是字符串,其余是错误。我想把堆栈跟踪也放在这里,以防它有帮助。您将如何使用递归编写它。你会用另一种方法吗?我可以试试看它是否有效。我必须使用递归,不能使用循环。方法可以改变。我的方法就是老师告诉我的。
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;
    }
}
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));
}