每日算法练习:LeetCode 125. 验证回文串 ✅

大家好,我是你们的算法小伙伴。今天我们来练习一道字符串处理的经典基础题 ------LeetCode 125. 验证回文串。这道题考察字符串的预处理和双指针的应用,难度适中,是面试中常见的字符串类入门题目,既能巩固基础语法,也能锻炼解题思路的严谨性。

题目描述

给定一个字符串s ,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

复制代码
输入:s = "A man, a plan, a canal: Panama"

输出:true

解释:"amanaplanacanalpanama" 是回文串。

示例 2:

复制代码
输入:s = "race a car"

输出:false

解释:"raceacar" 不是回文串。

示例 3:

复制代码
输入:s = " "

输出:true

解释:空字符串是回文串。

提示:

1 <= s.length <= 2 * 10⁵

字符串 s 由 ASCII 字符组成

解题思路

核心定义拆解

回文串的核心定义:正读和反读完全相同的字符串。本题有两个关键限制:

  1. 只考虑 字母和数字字符,忽略标点、空格等其他字符;

  2. 忽略字母的大小写(例如 'A' 和 'a' 视为相同字符)。

解题的核心思路的是:先对字符串进行预处理,过滤无效字符并统一大小写,再验证处理后的字符串是否为回文。

方法一:预处理 + 双指针

**思路:**先遍历原字符串,过滤掉非字母数字的字符,同时将所有字母转为统一大小写(小写或大写),得到一个纯字母数字的字符串;再用双指针从字符串两端向中间遍历,逐一对比对应位置的字符,若所有字符都相等,则为回文串。

方法二:原地双指针

**思路:**无需额外存储预处理后的字符串,直接在原字符串上使用双指针。左指针从头部、右指针从尾部开始,遇到非字母数字的字符则跳过,遇到字母则统一转为小写(或大写)后对比,直至指针相遇。该方法无需额外空间,效率更高。

代码实现

方法一:预处理 + 双指针

java 复制代码
class Solution {
    public boolean isPalindrome(String s) {
        // 1. 预处理:过滤非字母数字字符,统一转为小写
        StringBuilder filtered = new StringBuilder();
        for (char c : s.toCharArray()) {
            // 判断当前字符是否为字母或数字
            if (Character.isLetterOrDigit(c)) {
                filtered.append(Character.toLowerCase(c));
            }
        }
        // 2. 双指针验证回文
        int left = 0;
        int right = filtered.length() - 1;
        while (left < right) {
            // 对比左右指针指向的字符
            if (filtered.charAt(left) != filtered.charAt(right)) {
                return false;
            }
            left++;  // 左指针右移
            right--; // 右指针左移
        }
        return true;
    }
}

方法二:原地双指针(空间优化)

java 复制代码
class Solution {
    public boolean isPalindrome(String s) {
        int left = 0;
        int 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 (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

代码详解

一、预处理 + 双指针

  1. StringBuilder filtered = new StringBuilder();:用于存储预处理后的纯字母数字字符串,避免字符串拼接的性能损耗(String 不可变,拼接会产生新对象)。

  2. Character.isLetterOrDigit(c):判断字符c 是否为字母或数字,精准过滤标点、空格等无效字符。

  3. Character.toLowerCase(c):将字母转为小写,消除大小写差异(例如 'A' 和 'a' 统一为 'a')。

  4. 双指针遍历:左指针从 0 开始(字符串头部),右指针从 filtered.length() - 1 开始(字符串尾部),每次对比后指针向中间移动,若出现字符不相等则直接返回 false,直至指针相遇。

示例 1 模拟:

输入 "A man, a plan, a canal: Panama"

预处理后 → "amanaplanacanalpanama",双指针从两端对比,所有字符均相等,返回 true。

二、原地双指针

  1. 跳过无效字符:两个内层 while 循环分别控制左、右指针,遇到非字母数字字符则跳过,直至找到有效字符或指针相遇。

  2. 字符对比:找到有效字符后,统一转为小写对比,若不相等则返回 false;若相等则指针继续向中间移动。

  3. 优势:无需额外存储字符串,节省空间,尤其适合处理大规模字符串(如提示中长度达 2*10⁵ 的字符串)。

示例 2 模拟:

输入 "race a car"

原地遍历:左指针找到 'r',右指针找到 'r' → 相等;继续移动,左指针找到 'a',右指针找到 'a' → 相等;再移动,左指针找到 'c',右指针找到 'c' → 相等;继续移动,左指针找到 'e',右指针找到 'a' → 不相等,返回 false。

复杂度分析

解法 时间复杂度 空间复杂度 优点 缺点
预处理 + 双指针 O(n) O(n) 思路直观,代码简洁,易理解,不易出错 需要额外存储预处理后的字符串,占用空间
原地双指针 O(n) O(1) 空间最优,适合大规模字符串,效率更高 需要处理指针跳过无效字符的逻辑,细节稍多

总结

验证回文串的核心:先过滤无效字符、统一大小写,再通过双指针验证对称性。

  • 面试中,若不要求空间优化,优先写「预处理 + 双指针」解法,代码简洁、不易出错,能快速完成答题。

  • 若面试官要求空间复杂度 O(1),则使用「原地双指针」解法,重点注意跳过无效字符的逻辑,避免指针越界。

  • 本题的关键细节:忽略大小写、只考虑字母数字,这两个点容易遗漏,解题时需重点关注。

今天的每日算法练习就到这里,我们明天再见!👋

相关推荐
We་ct2 小时前
LeetCode 295. 数据流的中位数:双堆解法实战解析
开发语言·前端·数据结构·算法·leetcode·typescript·数据流
青槿吖2 小时前
第一篇:Redis集群从入门到踩坑:3主3从保姆级搭建+核心原理一次性讲透|面试必看
前端·redis·后端·面试·职场和发展·bootstrap·html
Aaron15883 小时前
RFSOC+VU13P/VU9P+GPU通用一体化硬件平台
人工智能·算法·fpga开发·硬件架构·硬件工程·信息与通信·基带工程
c++逐梦人3 小时前
DFS剪枝与优化
算法·深度优先·剪枝
量化炼金 (CodeAlchemy)3 小时前
【交易策略】基于随机森林的市场结构预测:机器学习在量化交易中的实战应用
算法·随机森林·机器学习
coder_Eight3 小时前
LRU 缓存实现详解:双向链表 + 哈希表
前端·算法
重生之我是Java开发战士3 小时前
【动态规划】路径问题:不同路径,珠宝的最高价值,下降路径最小和,最小路径和,地下城游戏
算法·游戏·动态规划
小辉同志3 小时前
739. 每日温度
c++·算法·leetcode
Via_Neo3 小时前
二进制枚举
数据结构·算法·leetcode