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

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

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

给你一个字符串 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 字符组成

题目来源:
作者:LeetCode
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xne8id/
来源:力扣(LeetCode)

自己想的方法:

方法一:先转小写拆分为数组,再过滤不符合条件的字符,再利用双指针进行比较

class Solution {

    /**
     * @param String $s
     * @return Boolean
     */
    function isPalindrome($s) {
        //符合条件的字符
        $legal_array = [
            0,1,2,3,4,5,6,7,8,9,
            "a","b","c","d","e",
            "f","g","h","i","j",
            "k","l","m","n","o",
            "p","q","r","s","t",
            "u","v","w","x","y","z"
        ];

        $s_arr = str_split(strtolower($s)); //一概转为小写并划分为数组
        foreach($s_arr as $k => $v){
            if(!in_array($v,$legal_array)){ //过滤不符合条件的字符串
                unset($s_arr[$k]);
            }
        }
       
        if(count($s_arr) == 0){
            return true;
        }
        $s_arr = array_values($s_arr);  //重置下标索引从0开始

        //对称比较,如有不等返回false
        $letf = 0;
        $right = count($s_arr) - 1;
        while($letf < $right){
            if($s_arr[$letf] != $s_arr[$right]){
                return false;
            }
            $letf++;
            $right--;
        }

        return true;
	}
}

$s = "A man, a plan, a canal: Panama";
$solution = new Solution();
$result = $solution->isPalindrome($s);
var_dump($result);
/**
输出结果为:bool(true)
*/

方法二:先正则过滤掉不符合条件的字符并转小写,再反转处理后的字符串,最后判断反转前后的字符串是否相等

class Solution {

    /**
     * @param String $s
     * @return Boolean
     */
    function isPalindrome($s) {
        //过滤非字母数字字符并转小写
        $leagal_str = strtolower(preg_replace('/[^a-z0-9]/i','',$s));
        //反转处理后的字符串
        $rev_str = strrev($leagal_str);
        //相等则为true否则为false
        if($leagal_str != $rev_str){
            return false;
        }
        return true;  
	}
}

$s = "A man, a plan, a canal: Panama";
$solution = new Solution();
$result = $solution->isPalindrome($s);
var_dump($result);
/**
输出结果为:bool(true)
*/

方法三:与方法一差不多,先正则处理不符合条件的字符,拆分为数组,再比较对称

class Solution {

    /**
     * @param String $s
     * @return Boolean
     */
    function isPalindrome($s) {
        //过滤非字母数字字符并转小写
        $leagal_str = strtolower(preg_replace('/[^a-z0-9]/i','',$s));
        if(strlen($leagal_str) == 0){
            return true;
        }
        //拆分为数组
        $leagal_str_array = str_split($leagal_str);

        //对称比较
        $left = 0;
        $right = count($leagal_str_array) - 1;
        while($left < $right){
            if($leagal_str_array[$left] != $leagal_str_array[$right]){
                return false;
            }
            $left++;
            $right--;
        }
        return true; 
	}
}

$s = "A man, a plan, a canal: Panama";
$solution = new Solution();
$result = $solution->isPalindrome($s);
var_dump($result);
/**
输出结果为:bool(true)
*/

官方解题方法:(与自己想的方法大体是差不多的)

一:双指针解决

这题没什么难度,最简单的就是使用双指针,一个指向前,一个指向后,遇到空格以及特殊字符要跳过,然后判断,画个图来看下
在这里插入图片描述

    public boolean isPalindrome(String s) {
        if (s.length() == 0)
            return true;
        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--;
            //然后把两个字符变为小写,在判断是否一样,如果不一样,直接返回false
            if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right)))
                return false;
            left++;
            right--;
        }
        return true;
    }

二:双指针的另一种写法

我们还可以在比较之前字母全部转化为小写,这里改为for循环的方式,只不过是换汤不换药,原理还都是一样的

    public boolean isPalindrome(String s) {
        if (s == null || s.length() == 0)
            return true;
        s = s.toLowerCase();
        for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
            while (i < j && !Character.isLetterOrDigit(s.charAt(i)))
                i++;
            while (i < j && !Character.isLetterOrDigit(s.charAt(j)))
                j--;
            if (s.charAt(i) != s.charAt(j))
                return false;
        }
        return true;
    }

三:使用正则匹配

这题还可以使用正则匹配,把特殊字符过滤掉,只留下字母和数字,然后转化为小写,再反转,最后在判断是否相等。

    public boolean isPalindrome(String s) {
        String actual = s.replaceAll("[^A-Za-z0-9]", "").toLowerCase();
        String rev = new StringBuffer(actual).reverse().toString();
        return actual.equals(rev);
    }

四:递归方式实现

如果想玩出花样,我们还可以把第一种的解题思路改为递归的方式

    public boolean isPalindrome(String s) {
        return isPalindromeHelper(s, 0, s.length() - 1);
    }

    public boolean isPalindromeHelper(String s, int left, int right) {
        if (left >= right)
            return true;
        while (left < right && !Character.isLetterOrDigit(s.charAt(left)))
            left++;
        while (left < right && !Character.isLetterOrDigit(s.charAt(right)))
            right--;
        return Character.toLowerCase(s.charAt(left)) == Character.toLowerCase(s.charAt(right)) && isPalindromeHelper(s, ++left, --right);
    }

官方解题来源:
作者:数据结构和算法
链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xne8id/?discussion=BHK3ga
来源:力扣(LeetCode)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值