leetcode
leetcode 101 ~ 150
验证回文串

验证回文串

难度:

标签:

题目描述

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

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

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

代码结果

运行时间: 20 ms, 内存: 17.6 MB


/*
题目思路:
1. 使用Java Stream API处理字符串。
2. 移除所有非字母数字字符,将所有大写字母转换为小写字母。
3. 检查处理后的字符串是否是回文串。
*/
 
import java.util.stream.Collectors;
 
public class Solution {
    public boolean isPalindrome(String s) {
        // 使用流API过滤非字母数字字符并转换为小写
        String filtered = s.chars()
            .filter(Character::isLetterOrDigit)
            .mapToObj(c -> String.valueOf((char) c).toLowerCase())
            .collect(Collectors.joining());
        // 反转字符串
        String reversed = new StringBuilder(filtered).reverse().toString();
        // 检查是否回文
        return filtered.equals(reversed);
    }
}
 

解释

方法:

此题解通过首先将输入字符串转换为小写,然后利用filter函数结合str.isalnum方法移除所有非字母数字字符,得到纯净的字符串s。随后,通过比较字符串的前半部分和后半部分(反向)的字符是否一致来判断字符串是否为回文。如果在比较过程中发现不匹配的字符,则立即返回false。如果所有对应位置的字符都相同,最终返回true。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在实现过程中,为什么选择先将字符串转化为小写再过滤非字母数字字符,这样的顺序是否有特别的考虑?
在处理回文字符串时,重要的一步是确保比较的一致性和无歧义性。将字符串先转化为小写是为了消除大写和小写字符之间的差异,确保回文比较时字符的统一性。此操作后再过滤非字母数字字符,是因为大小写转换仅适用于字母,而非字母数字字符在回文验证中无意义,应被排除。如果先过滤再转换小写,可能会有不必要的性能开销,因为非字母数字字符无需转换。因此,这样的顺序既逻辑合理又效率较高。
🦆
对于空字符串或只包含非字母数字字符的字符串,算法是如何处理的?
对于空字符串或只包含非字母数字字符的字符串,在过滤非字母数字字符后,结果将是一个空字符串。在此算法中,空字符串被认为是回文,因为回文的定义是正向和反向读都一样,空字符串符合这一标准。因此,算法将返回true。
🦆
算法中使用双循环来比较字符是否相等,是否存在更高效的方法来减少比较次数或提高效率?
算法实际上只使用了一个单层循环来从两端向中心比较字符直到中间的位置。这是一种高效的方法,因为它最多只比较字符串的一半字符。尽管如此,还可以通过一些技术进一步提高效率,例如使用双指针技术从两端向中心移动,这可以稍微减少代码复杂性并可能提高一些实际运行效率。然而,基本的时间复杂度仍然是 O(n)。
🦆
为什么算法中使用`filter`和`str.isalnum`函数而不是正则表达式进行字符过滤?
使用`filter`和`str.isalnum`的原因主要是代码的可读性和简洁性。`str.isalnum`直接检测字符是否是字母或数字,非常直观且易于理解。虽然正则表达式同样可以实现字符过滤的功能,但它通常更复杂,对于初学者可能不够友好。此外,对于这种简单的字符检测,`str.isalnum`在功能上完全足够,且执行效率通常与正则表达式相当。

相关问题

回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

 

示例 1:

输入:head = [1,2,2,1]
输出:true

示例 2:

输入:head = [1,2]
输出:false

 

提示:

  • 链表中节点数目在范围[1, 105]
  • 0 <= Node.val <= 9

 

进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

验证回文串 II

给你一个字符串 s最多 可以从中删除一个字符。

请你判断 s 是否能成为回文字符串:如果能,返回 true ;否则,返回 false

 

示例 1:

输入:s = "aba"
输出:true

示例 2:

输入:s = "abca"
输出:true
解释:你可以删除字符 'c' 。

示例 3:

输入:s = "abc"
输出:false

 

提示:

  • 1 <= s.length <= 105
  • s 由小写英文字母组成