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

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

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

相关推荐
轻颂呀1 小时前
约瑟夫环问题
算法
科技大视界3 小时前
投资AI项目,传统尽调不够用了——李章虎律师拆解算法、数据、算力三大雷区
人工智能·算法·数据挖掘
郝学胜-神的一滴3 小时前
算法实战:最小k个数——大顶堆的优雅解法
开发语言·数据结构·c++·python·程序人生·算法·排序算法
Irissgwe3 小时前
算法滑动窗口
数据结构·算法
怪兽学LLM3 小时前
LeetCode 105. 从前序与中序遍历序列构造二叉树:分治递归思路详解
算法·leetcode·职场和发展
可编程芯片开发3 小时前
基于PI控制的三相整流器控制系统的simulink建模与仿真,包含超级电容充电和电机
算法
酿情师4 小时前
区块链共识算法深度拆解:PoW、PoS、PBFT、Raft 原理解析
算法·区块链·共识算法
hansang_IR4 小时前
【记录】「SCOI2016」三道模拟赛/26.7.12
c++·算法
QQ骞4 小时前
【ECU-HIL 嵌入式车载软件测试学习路线和面试描述方式(1)】
学习·面试·职场和发展
退休倒计时4 小时前
【每日一题】LeetCode 39. 组合总和 TypeScript
算法·leetcode·typescript