验证回文串

题目描述

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。

字母和数字都属于字母数字字符。

给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 

示例 1:

输入: s = "A man, a plan, a canal: Panama"
输出:true
解释:"amanaplanacanalpanama" 是回文串。

示例 2:

输入:s = "race a car"
输出:false
解释:"raceacar" 不是回文串。

示例 3:

输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。
由于空字符串正着反着读都一样,所以是回文串。

提示:

  • 1 <= s.length <= 2 * 105
  • s 仅由可打印的 ASCII 字符组成

题目分析

 回文串:正着读反着读都一样,比如说:

0110

0shhs0

这个题目是将字母大小写看作一样,所以在做的时候可以将字母全部转换为大写或者全部转换为小写。

题目的判断的回文串中,不仅包括字母,还有数字。

所以在判断字符串中的字符是否是有效字符 (可以用来判断是否是回文的字符) 时 ,还要把数字考虑进去。可以使用 isLetterOrDigit 方法,我刚开始做的时候,就是没看到数字也算有效字符,就导致总是错误。所以,审题要仔细。

题目解析

 解法一

        先将字符串遍历一遍,剔除所有无效字符 (非字母和数字) ,将所有有效字符放在一个新字符数组里,再基于新的字符数组进行判断。

解法二

        在不考虑字符串中有无效字符的情况下,比如:

ABCCBA

        在这种情况下判断回文, 就可以设两个指针 left,right,分别指向字符串的最左边字符,和最右边字符。当判断到 left 和 right 指向的字符相等时,将 left 右移,right 左移,继续判断两个字符是否相等。直到遍历完整个字符串,即 left >= right。在此过程中,如果有两个元素不相等的情况,直接返回 false,说明该字符串不是回文串。反之,如果遍历完整个字符串,都没有,那就在循环结束后,返回 true 即可。

        对于含有无效字符的字符串的判断,就只用基于不含无效字符的解法上加一步,那就是判断是否是无效字符,如果是无效字符,那直接跳过即可。直到 left 和 right 指向的字符都是有效字符时,再判断 left 和 right 指向字符是否相等,不等,返回 false;相等,继续向后判断。

        在跳过无效字符时,也需要实时判断 left < right,不能跳过了。

        在跳过无效字符过后,对两个字符进行相等判断之前,也需要判断 left < right,因为在跳跃之后,可能会出现 left == right 的情况,那此时指向的是同一个字符,无需判断。算是一个小优化,其实不判断也不会错,只是效率没那么高。

时间复杂度:O(N)

空间复杂度:O(1)

 代码

class Solution {
    public boolean isPalindrome(String s) {
        int left = 0, right = s.length() - 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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值