每日算法练习: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),则使用「原地双指针」解法,重点注意跳过无效字符的逻辑,避免指针越界。

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

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

相关推荐
kobesdu3 小时前
人形机器人SLAM:技术挑战、算法综述与开源方案
算法·机器人·人形机器人
椰羊~王小美4 小时前
随机数概念及算法
算法
阿Y加油吧5 小时前
算法实战笔记:LeetCode 169 多数元素 & 75 颜色分类
笔记·算法·leetcode
不要秃头的小孩5 小时前
力扣刷题——509. 斐波那契数
python·算法·leetcode·动态规划
We་ct6 小时前
LeetCode 120. 三角形最小路径和:动态规划详解
前端·javascript·算法·leetcode·typescript·动态规划
蒸汽求职6 小时前
破局“无效互面”:跨国大厂视角的工业级 Mock Interview 价值解析
缓存·面试·职场和发展·金融·notion
py有趣6 小时前
力扣热门100题之和为K的子数组
数据结构·算法·leetcode
hipolymers6 小时前
C语言怎么样?难学吗?
c语言·数据结构·学习·算法·编程
workflower8 小时前
机器人应用-楼宇室内巡逻
大数据·人工智能·算法·microsoft·机器人·动态规划·享元模式