1. 引言

本文将介绍在Java中如何判断给定字符串是否为回文。回文是指正读反读都相同的字符序列,例如"madam"或"racecar"。作为有经验的开发者,这类基础算法问题应该快速掌握,但实现方式有多种,每种都有其适用场景。

2. 解决方案

下面我们通过几种不同方式实现回文检测,每种方案都有其优缺点,可根据实际需求选择。

2.1. 简单粗暴的双指针法

最直观的方法是同时从字符串两端向中间遍历,逐个字符比较:

public boolean isPalindrome(String text) {
    String clean = text.replaceAll("\\s+", "").toLowerCase();
    int length = clean.length();
    int forward = 0;
    int backward = length - 1;
    while (backward > forward) {
        char forwardChar = clean.charAt(forward++);
        char backwardChar = clean.charAt(backward--);
        if (forwardChar != backwardChar)
            return false;
    }
    return true;
}

优点

  • 时间复杂度O(n/2),空间复杂度O(1)
  • 无需额外内存,适合处理超大字符串

⚠️ 注意:需先去除空格并统一大小写,避免"Race Car"这类字符串误判

2.2. 字符串反转法

通过反转字符串后与原字符串比较,实现方式可分为两类:

手动反转实现

public boolean isPalindromeReverseTheString(String text) {
    StringBuilder reverse = new StringBuilder();
    String clean = text.replaceAll("\\s+", "").toLowerCase();
    char[] plain = clean.toCharArray();
    for (int i = plain.length - 1; i >= 0; i--) {
        reverse.append(plain[i]);
    }
    return (reverse.toString()).equals(clean);
}

使用StringBuilder/StringBuffer

public boolean isPalindromeUsingStringBuilder(String text) {
    String clean = text.replaceAll("\\s+", "").toLowerCase();
    StringBuilder plain = new StringBuilder(clean);
    StringBuilder reverse = plain.reverse();
    return (reverse.toString()).equals(clean);
}

public boolean isPalindromeUsingStringBuffer(String text) {
    String clean = text.replaceAll("\\s+", "").toLowerCase();
    StringBuffer plain = new StringBuffer(clean);
    StringBuffer reverse = plain.reverse();
    return (reverse.toString()).equals(clean);
}

缺点

  • 需要O(n)额外空间存储反转字符串
  • StringBuilder和StringBuffer的reverse()方法内部实现效率不如双指针法

2.3. Stream API实现

利用Java 8的流式处理,代码更简洁:

public boolean isPalindromeUsingIntStream(String text) {
    String temp  = text.replaceAll("\\s+", "").toLowerCase();
    return IntStream.range(0, temp.length() / 2)
      .noneMatch(i -> temp.charAt(i) != temp.charAt(temp.length() - i - 1));
}

优点

  • 函数式风格,代码简洁
  • 并行流可提升处理速度(对超长字符串有效)

⚠️ 注意:对短字符串而言,流式处理的开销可能超过其优势

2.4. 递归实现

递归是解决此类问题的经典方法,但需注意栈溢出风险:

public boolean isPalindromeRecursive(String text){
    String clean = text.replaceAll("\\s+", "").toLowerCase();
    return recursivePalindrome(clean,0,clean.length()-1);
}

private boolean recursivePalindrome(String text, int forward, int backward) {
    if (forward == backward) {
        return true;
    }
    if ((text.charAt(forward)) != (text.charAt(backward))) {
        return false;
    }
    if (forward < backward + 1) {
        return recursivePalindrome(text, forward + 1, backward - 1);
    }
    return true;
}

缺点

  • 空间复杂度O(n)(调用栈深度)
  • 极长字符串可能导致StackOverflowError

3. 总结

方法 时间复杂度 空间复杂度 适用场景
双指针法 O(n) O(1) 超大字符串,内存敏感场景
字符串反转法 O(n) O(n) 简单场景,代码可读性优先
Stream API O(n) O(1) 并行处理,函数式编程风格
递归法 O(n) O(n) 教学示例,短字符串处理

推荐选择

  • 生产环境优先使用双指针法(性能最优)
  • 需要代码简洁时考虑Stream API
  • 避免在长字符串处理中使用递归

本文所有代码示例可在GitHub仓库获取完整实现。


原始标题:Check if a String Is a Palindrome in Java

« 上一篇: ActiveJDBC 入门指南
» 下一篇: Java 迷宫求解器