Java:回文查找花费的时间太长;如何优化?

Java:回文查找花费的时间太长;如何优化?,java,Java,我编写了一个函数来确定给定字符串(去掉空格)是否是回文。不幸的是,运行时间太长。有没有办法让下面的代码运行得更快?(我正在等待LeetCode的在线评委): 这不是查找字符串是否为回文的最佳方法 只需在n/2迭代中循环(其中n是string的长度),并检查i位置的字符是否等于n-i位置的字符。这不是确定字符串是否为回文的最佳方法 只需在n/2迭代中循环(其中n是字符串的长度i位置的字符是否等于n-i位置的字符,这是一种称为“分而治之”的算法方法。但在这种情况下,只是将其设为n/2而不是n.这是一

我编写了一个函数来确定给定字符串(去掉空格)是否是回文。不幸的是,运行时间太长。有没有办法让下面的代码运行得更快?(我正在等待LeetCode的在线评委):


这不是查找
字符串是否为回文的最佳方法


只需在
n/2
迭代中循环(其中
n
string
的长度),并检查
i
位置的字符是否等于
n-i

位置的字符。这不是确定
字符串是否为回文的最佳方法


只需在
n/2
迭代中循环(其中
n
字符串的长度
i
位置的字符是否等于
n-i

位置的字符,这是一种称为“分而治之”的算法方法。但在这种情况下,只是将其设为n/2而不是n.

这是一种称为“分而治之”的算法方法。但在这种情况下,只需将其设为n/2而不是n。

如果字符串
s
的长度为
n
,则
s
将是一个回文,如果

s[i]=s[n-1-i] for i in range [0,ceil(n/2)]  // 0 based index
代码:

public静态布尔checkIfPalindrome(字符串s){

对于(int i=0;i如果字符串
s
的长度为
n
,则
s
将是回文,如果

s[i]=s[n-1-i] for i in range [0,ceil(n/2)]  // 0 based index
代码:

public静态布尔checkIfPalindrome(字符串s){

对于(int i=0;i,这里有一个合适的算法可能会有所帮助:

1.对于
i=1到n/2

2.如果
string[i]=string[n-1]
在循环中继续

3.Else
break
返回false


4.
返回true

以下是一个合适的算法,可能会有所帮助:

1.对于
i=1到n/2

2.如果
string[i]=string[n-1]
在循环中继续

3.Else
break
返回false


4.
返回true

您可以使用此
StringBuilder.reverse()
检查回文:

    private boolean isPalindrome(String str) {
       StringBuilder strBuilder = new StringBuilder(str);
       return str.equals(strBuilder.reverse().toString());
    }

您可以使用此
StringBuilder.reverse()
检查回文:

    private boolean isPalindrome(String str) {
       StringBuilder strBuilder = new StringBuilder(str);
       return str.equals(strBuilder.reverse().toString());
    }

如果n是输入字符串的长度,则代码将执行O(n^2)操作。这可能会让您感到惊讶,因为代码中没有嵌套循环,但字符串的substring方法和+=运算符都需要创建新字符串,这需要复制其内容

为了看到这一点,我插入了

System.out.println(s); 
进入
isAlindrome()
checkIfPalindrome()
方法,并调用

isPalindrome("doc, note: i dissent. a fast never prevents a fatness. i diet on cod");
这将产生以下输出:

docnoteidissentafastneverpreventsafatnessidietoncod
ocnoteidissentafastneverpreventsafatnessidietonco
ocnoteidissentafastneverpreventsafatnessidietonco
cnoteidissentafastneverpreventsafatnessidietonc
cnoteidissentafastneverpreventsafatnessidietonc
noteidissentafastneverpreventsafatnessidieton
noteidissentafastneverpreventsafatnessidieton
oteidissentafastneverpreventsafatnessidieto
oteidissentafastneverpreventsafatnessidieto
teidissentafastneverpreventsafatnessidiet
teidissentafastneverpreventsafatnessidiet
eidissentafastneverpreventsafatnessidie
eidissentafastneverpreventsafatnessidie
idissentafastneverpreventsafatnessidi
idissentafastneverpreventsafatnessidi
dissentafastneverpreventsafatnessid
dissentafastneverpreventsafatnessid
issentafastneverpreventsafatnessi
issentafastneverpreventsafatnessi
ssentafastneverpreventsafatness
ssentafastneverpreventsafatness
sentafastneverpreventsafatnes
sentafastneverpreventsafatnes
entafastneverpreventsafatne
entafastneverpreventsafatne
ntafastneverpreventsafatn
ntafastneverpreventsafatn
tafastneverpreventsafat
tafastneverpreventsafat
afastneverpreventsafa
afastneverpreventsafa
fastneverpreventsaf
fastneverpreventsaf
astneverpreventsa
astneverpreventsa
stneverprevents
stneverprevents
tneverprevent
tneverprevent
neverpreven
neverpreven
everpreve
everpreve
verprev
verprev
erpre
erpre
rpr
rpr
p
p
我们要求计算机计算的文本太多了!我们还看到每个字符串都创建了两次。这是因为在每次迭代中,您不需要只调用characters()

要避免创建中间字符串实例,可以使用字符串生成器:

String onlyCharacters(String s) {
    StringBuilder toReturn = new StringBuilder();
    for (Character c : s.toCharArray()) {
        if (Character.isLetter(c)) {
            toReturn.append(c);
        }
    }
    return toReturn.toString();
}
此外,StringBuilder还有一个很酷的方法,名为reverse(),因此我们可以将您的程序简化为:

boolean isPalindrome(String s) {
    StringBuilder letters = new StringBuilder();
    for (Character c : s.toCharArray()) {
        if (Character.isLetter(c)) {
            letters.append(c);
        }
    }
    StringBuilder reversedLetters = new StringBuilder(letters).reverse();
    return onlyLetters.equals(reversedLetters);
}

此代码仅创建
2
StringBuilder对象,而不是
n
字符串,因此大约比代码快
n/2
倍。

如果n是输入字符串的长度,则代码取O(n^2)操作。这可能会让您感到惊讶,因为代码中没有嵌套循环,但字符串的substring方法和+=运算符都需要创建新字符串,这需要复制其内容

为了看到这一点,我插入了

System.out.println(s); 
进入
isAlindrome()
checkIfPalindrome()
方法,并调用

isPalindrome("doc, note: i dissent. a fast never prevents a fatness. i diet on cod");
这将产生以下输出:

docnoteidissentafastneverpreventsafatnessidietoncod
ocnoteidissentafastneverpreventsafatnessidietonco
ocnoteidissentafastneverpreventsafatnessidietonco
cnoteidissentafastneverpreventsafatnessidietonc
cnoteidissentafastneverpreventsafatnessidietonc
noteidissentafastneverpreventsafatnessidieton
noteidissentafastneverpreventsafatnessidieton
oteidissentafastneverpreventsafatnessidieto
oteidissentafastneverpreventsafatnessidieto
teidissentafastneverpreventsafatnessidiet
teidissentafastneverpreventsafatnessidiet
eidissentafastneverpreventsafatnessidie
eidissentafastneverpreventsafatnessidie
idissentafastneverpreventsafatnessidi
idissentafastneverpreventsafatnessidi
dissentafastneverpreventsafatnessid
dissentafastneverpreventsafatnessid
issentafastneverpreventsafatnessi
issentafastneverpreventsafatnessi
ssentafastneverpreventsafatness
ssentafastneverpreventsafatness
sentafastneverpreventsafatnes
sentafastneverpreventsafatnes
entafastneverpreventsafatne
entafastneverpreventsafatne
ntafastneverpreventsafatn
ntafastneverpreventsafatn
tafastneverpreventsafat
tafastneverpreventsafat
afastneverpreventsafa
afastneverpreventsafa
fastneverpreventsaf
fastneverpreventsaf
astneverpreventsa
astneverpreventsa
stneverprevents
stneverprevents
tneverprevent
tneverprevent
neverpreven
neverpreven
everpreve
everpreve
verprev
verprev
erpre
erpre
rpr
rpr
p
p
我们要求计算机计算的文本太多了!我们还看到每个字符串都创建了两次。这是因为在每次迭代中,您不需要只调用characters()

要避免创建中间字符串实例,可以使用字符串生成器:

String onlyCharacters(String s) {
    StringBuilder toReturn = new StringBuilder();
    for (Character c : s.toCharArray()) {
        if (Character.isLetter(c)) {
            toReturn.append(c);
        }
    }
    return toReturn.toString();
}
此外,StringBuilder还有一个很酷的方法,名为reverse(),因此我们可以将您的程序简化为:

boolean isPalindrome(String s) {
    StringBuilder letters = new StringBuilder();
    for (Character c : s.toCharArray()) {
        if (Character.isLetter(c)) {
            letters.append(c);
        }
    }
    StringBuilder reversedLetters = new StringBuilder(letters).reverse();
    return onlyLetters.equals(reversedLetters);
}

此代码只创建
2
StringBuilder对象,而不是
n
字符串,因此比您的代码快约
n/2
倍。

我发现这比目前为止的任何其他答案都快:

public class Solution {

  public boolean isPalindrome(String s) {
    for (int low = 0, high = s.length() - 1;; low++, high--) {
      char cLow = 0, cHigh = 0;

      // Find the next acceptable character for the increasing index.
      while (low < high && !Character.isLetterOrDigit(cLow = s.charAt(low))) {
        low++;
      }

      // Find the previous acceptable character for the decreasing index.
      while (low < high && !Character.isLetterOrDigit(cHigh = s.charAt(high))) {
        high--;
      }

      if (low >= high) {
        // All previous character comparisons succeeded and we have a palindrome.
        return true;
      }

      if (Character.toUpperCase(cLow) != Character.toUpperCase(cHigh)) {
        // This is not a palindrome.
        return false;
      }
    }
  }
}
公共类解决方案{
公共布尔值isAlindrome(字符串s){
对于(int-low=0,high=s.length()-1;;low++,high--){
char-cLow=0,cHigh=0;
//为递增索引查找下一个可接受的字符。
while(low=高){
//之前所有的字符比较都成功了,我们有一个回文。
返回true;
}
if(Character.toUpperCase(cLow)!=Character.toUpperCase(cHigh)){
//这不是回文。
返回false;
}
}
}
}
您只有一个对象:原始的
字符串
。将测试每个字符,直到获得可接受的字符(
character.isleter
)。然后仅对这些字符进行比较

没有临时对象,没有超级检查。直奔目标:它做一件事,但做得很好


注意:这通过检查字母数字而不是仅检查字母数字来回答实际的Leetcode OJ答案,并且不考虑大小写。

我发现这比目前为止的任何其他答案都要快:

public class Solution {

  public boolean isPalindrome(String s) {
    for (int low = 0, high = s.length() - 1;; low++, high--) {
      char cLow = 0, cHigh = 0;

      // Find the next acceptable character for the increasing index.
      while (low < high && !Character.isLetterOrDigit(cLow = s.charAt(low))) {
        low++;
      }

      // Find the previous acceptable character for the decreasing index.
      while (low < high && !Character.isLetterOrDigit(cHigh = s.charAt(high))) {
        high--;
      }

      if (low >= high) {
        // All previous character comparisons succeeded and we have a palindrome.
        return true;
      }

      if (Character.toUpperCase(cLow) != Character.toUpperCase(cHigh)) {
        // This is not a palindrome.
        return false;
      }
    }
  }
}
公共类解决方案{
公共布尔值isAlindrome(字符串s){
对于(int-low=0,high=s.length()-1;;low++,high--){
char-cLow=0,cHigh=0;
//为递增索引查找下一个可接受的字符。
while(低