给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
    说明:本题中,我们将空字符串定义为有效的回文串。

    示例 1:
    输入: “A man, a plan, a canal: Panama”
    输出: true
    解释:”amanaplanacanalpanama” 是回文串

    示例 2:
    输入: “race a car”
    输出: false
    解释:”raceacar” 不是回文串

    题目要求只考虑字母和数字字符,忽略字母的大小写,那么可以先处理一下原始字符串:

    1. public String filter(String s) {
    2. StringBuilder strBuilder = new StringBuilder();
    3. int length = s.length();
    4. for (int i = 0; i < length; i++) {
    5. char ch = s.charAt(i);
    6. // 只考虑字母和数字字符
    7. if (Character.isLetterOrDigit(ch)) {
    8. // 都转小写
    9. strBuilder.append(Character.toLowerCase(ch));
    10. }
    11. }
    12. return strBuilder.toString();
    13. }

    可以利用 StringBuilder 反转一下字符串,然后进行比较:

    1. public boolean isPalindrome(String s) {
    2. // 获取仅数字和字母的字符
    3. String str = filter(s);
    4. // 反转字符串
    5. String revStr = new StringBuilder(str).reverse().toString();
    6. return str.equals(revStr);
    7. }

    也可以利用双指针比较字符:

    1. public boolean isPalindrome(String s) {
    2. String str = filter(s);
    3. int n = str.length();
    4. int left = 0, right = n - 1;
    5. while (left < right) {
    6. if (str.charAt(left) != str.charAt(right)) {
    7. return false;
    8. }
    9. ++left;
    10. --right;
    11. }
    12. return true;
    13. }

    也可以直接双直线原地比较:

    1. public boolean isPalindrome(String s) {
    2. int n = s.length();
    3. int left = 0, right = n - 1;
    4. while (left < right) {
    5. // 若左指针指向的字符不是数字和字母,则左指针右移一位
    6. while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
    7. ++left;
    8. }
    9. // 若右指针指向的字符不是数字和字母,则右指针左移一位
    10. while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
    11. --right;
    12. }
    13. if (left < right) {
    14. // 忽略大小写进行比较
    15. if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {
    16. return false;
    17. }
    18. ++left;
    19. --right;
    20. }
    21. }
    22. return true;
    23. }