剑指 Offer II 018. 有效的回文(125. 验证回文串)

题目:

 

 

思路:

【1】利用内置函数的方式

【2】利用双指针的方式,因为本质上就是回文字符串两边是相等的。

【3】基于双指针上面做位运算进行优化加快效率

【基于位运算的大小写转换技巧】
观察如下四个字母的ASCII码值。
'A': 65  = 1000001
'a': 97  = 1100001
'Z': 90  = 1011010
'z': 122 = 1111010
可以发现大小写之间只差了100000,即十进制的32。
于是对于字符ch有:
ch ^ 32  大小写反转
ch | 32  大写转小写
ch & ~32 小写转大写

 

 

 

代码展示:

基于双指针上面做位运算进行优化:

//时间1 ms击败100%
//内存41.4 MB击败69.97%
class Solution {
    public boolean isPalindrome(String s) {
        int l = 0, r = s.length() - 1;
        char[] arr = s.toCharArray();
        while(l < r){
            while(l < r && !isValid(arr[l])) l++;
            while(l < r && !isValid(arr[r])) r--;
            if(arr[l] != arr[r] && arr[l] != (arr[r] ^ 32)){
                return false;
            }
            l++;
            r--;
        }
        return true;
    }
    private boolean isValid(char x){
        int val = x - '0';
        if(val <= 9 && val >= 0) return true; // 是数字
        val = x - 'a';
        if(val <= 25 && val >= 0) return true; // 是小写字母
        val = x - 'A';
        if(val <= 25 && val >= 0) return true; // 是大写字母
        return false;
    }
}

 

利用双指针的方式:

//时间2 ms击败93.44%
//内存41 MB击败98.93%
class Solution {
    public boolean isPalindrome(String s) {
        int n = s.length();
        int left = 0, right = n - 1;
        while (left < right) {
            //两个指针如果遇到不是数字或者字母的就跳过
            while (left < right && !Character.isLetterOrDigit(s.charAt(left))) ++left;
            while (left < right && !Character.isLetterOrDigit(s.charAt(right))) --right;
            //比较字符是否相等(这里面应把大写的也转换成小写)
            if (left < right) {
                if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {
                    //遇到不同则不是回文字符串
                    return false;
                }
                ++left;
                --right;
            }
        }
        return true;
    }
}

 

利用内置函数的方式:

//时间4 ms击败36.31%
//内存41.4 MB击败70.97%
class Solution {
    public boolean isPalindrome(String s) {
        StringBuffer sgood = new StringBuffer();
        int length = s.length();
        //先单次遍历
        for (int i = 0; i < length; i++) {
            char ch = s.charAt(i);
            //将是字符和数字的挑出来
            if (Character.isLetterOrDigit(ch)) {
                //转为小写后塞入
                sgood.append(Character.toLowerCase(ch));
            }
        }
        //复制出反转的副本
        StringBuffer sgood_rev = new StringBuffer(sgood).reverse();
        //两者比较,相等的就是回文字符串
        return sgood.toString().equals(sgood_rev.toString());
    }
}

 

posted @ 2023-02-28 18:24  忧愁的chafry  阅读(12)  评论(0编辑  收藏  举报